Index: lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.td +++ lib/Target/AArch64/AArch64RegisterInfo.td @@ -841,6 +841,14 @@ let Namespace = "AArch64" in { def zsub0 : SubRegIndex<128, -1>; + def zsub1 : SubRegIndex<128, -1>; +} + +// Pairs, triples, and quads of SVE vector registers. +def ZSeqPairs : RegisterTuples<[zsub0, zsub1], [(rotl ZPR, 0), (rotl ZPR, 1)]>; + +def ZPR2 : RegisterClass<"AArch64", [untyped], 128, (add ZSeqPairs)> { + let Size = 256; } class ZPRVectorList : AsmOperandClass { @@ -866,3 +874,19 @@ def Z_d : RegisterOperand"> { let ParserMatchClass = ZPRVectorList<64, 1>; } + +def ZZ_b : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<8, 2>; +} + +def ZZ_h : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<16, 2>; +} + +def ZZ_s : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<32, 2>; +} + +def ZZ_d : RegisterOperand"> { + let ParserMatchClass = ZPRVectorList<64, 2>; +} Index: lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64SVEInstrInfo.td +++ lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -38,6 +38,12 @@ defm LD1SB_H_IMM : sve_mem_cld_si<0b1110, "ld1sb", Z_h, ZPR16>; defm LD1D_IMM : sve_mem_cld_si<0b1111, "ld1d", Z_d, ZPR64>; + // LD(2|3|4) structured loads with reg+immediate + defm LD2B_IMM : sve_mem_eld_si<0b00, 0b01, ZZ_b, "ld2b", simm4Scale2MulVl>; + defm LD2H_IMM : sve_mem_eld_si<0b01, 0b01, ZZ_h, "ld2h", simm4Scale2MulVl>; + defm LD2W_IMM : sve_mem_eld_si<0b10, 0b01, ZZ_s, "ld2w", simm4Scale2MulVl>; + defm LD2D_IMM : sve_mem_eld_si<0b11, 0b01, ZZ_d, "ld2d", simm4Scale2MulVl>; + // continuous store with immediates defm ST1B_IMM : sve_mem_cst_si<0b00, 0b00, "st1b", Z_b, ZPR8>; defm ST1B_H_IMM : sve_mem_cst_si<0b00, 0b01, "st1b", Z_h, ZPR16>; Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -1154,11 +1154,11 @@ AArch64::Q0, AArch64::Q0_Q1, AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 }, /* ZReg */ { AArch64::Z0, - AArch64::Z0 } + AArch64::Z0, AArch64::Z0_Z1 } }; - assert((RegTy != VecListIdx_ZReg || NumRegs <= 1) && - " NumRegs must be 0 or 1 for ZRegs"); + assert((RegTy != VecListIdx_ZReg || NumRegs <= 2) && + " NumRegs must be <= 2 for ZRegs"); unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs]; Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() - @@ -3647,6 +3647,8 @@ return Error(Loc, "index must be an integer in range [-16, 15]."); case Match_InvalidMemoryIndexed1SImm4: return Error(Loc, "index must be an integer in range [-8, 7]."); + case Match_InvalidMemoryIndexed2SImm4: + return Error(Loc, "index must be a multiple of 2 in range [-16, 14]."); case Match_InvalidMemoryIndexedSImm9: return Error(Loc, "index must be an integer in range [-256, 255]."); case Match_InvalidMemoryIndexedSImm10: @@ -4162,6 +4164,7 @@ case Match_InvalidMemoryXExtend64: case Match_InvalidMemoryXExtend128: case Match_InvalidMemoryIndexed1SImm4: + case Match_InvalidMemoryIndexed2SImm4: case Match_InvalidMemoryIndexed4SImm7: case Match_InvalidMemoryIndexed8SImm7: case Match_InvalidMemoryIndexed16SImm7: Index: lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -88,6 +88,9 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); +static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); @@ -471,6 +474,27 @@ return Success; } +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, + AArch64::Z8_Z9, AArch64::Z9_Z10, AArch64::Z10_Z11, AArch64::Z11_Z12, + AArch64::Z12_Z13, AArch64::Z13_Z14, AArch64::Z14_Z15, AArch64::Z15_Z16, + AArch64::Z16_Z17, AArch64::Z17_Z18, AArch64::Z18_Z19, AArch64::Z19_Z20, + AArch64::Z20_Z21, AArch64::Z21_Z22, AArch64::Z22_Z23, AArch64::Z23_Z24, + AArch64::Z24_Z25, AArch64::Z25_Z26, AArch64::Z26_Z27, AArch64::Z27_Z28, + AArch64::Z28_Z29, AArch64::Z29_Z30, AArch64::Z30_Z31, AArch64::Z31_Z0 +}; + +static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void* Decoder) { + if (RegNo > 31) + return Fail; + unsigned Register = ZZDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Register)); + return Success; +} + static const unsigned PPRDecoderTable[] = { AArch64::P0, AArch64::P1, AArch64::P2, AArch64::P3, AArch64::P4, AArch64::P5, AArch64::P6, AArch64::P7, Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1180,6 +1180,7 @@ // list). unsigned NumRegs = 1; if (MRI.getRegClass(AArch64::DDRegClassID).contains(Reg) || + MRI.getRegClass(AArch64::ZPR2RegClassID).contains(Reg) || MRI.getRegClass(AArch64::QQRegClassID).contains(Reg)) NumRegs = 2; else if (MRI.getRegClass(AArch64::DDDRegClassID).contains(Reg) || Index: lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- lib/Target/AArch64/SVEInstrFormats.td +++ lib/Target/AArch64/SVEInstrFormats.td @@ -36,12 +36,21 @@ } def SImm4MulVlOperand : SImmMulVlOperand<4,1>; +def SImm4Scale2MulVlOperand : SImmMulVlOperand<4,2>; def simm4MulVl : Operand, ImmLeaf= -8 && Imm < 8; }]> { let DecoderMethod = "DecodeSImm<4>"; let ParserMatchClass = SImm4MulVlOperand; } +def simm4Scale2MulVl : Operand, ImmLeaf= -16 && Imm <= 14) && ((Imm % 2) == 0x0); + }]> { + let DecoderMethod = "DecodeSImm<4>"; + let PrintMethod = "printImmScale<2>"; + let ParserMatchClass = SImm4Scale2MulVlOperand; +} + class SVELogicalImmOperand : AsmOperandClass { let Name = "SVELogicalImm" # Width; let DiagnosticType = "LogicalSecondSource"; @@ -618,4 +627,35 @@ multiclass sve_mem_cld_si dtype, string asm, RegisterOperand listty, ZPRRegOp zprty> -: sve_mem_cld_si_base; \ No newline at end of file +: sve_mem_cld_si_base; + +class sve_mem_eld_si sz, bits<2> nregs, RegisterOperand VecList, + string asm, Operand immtype> +: I<(outs VecList:$Zt), (ins PPR3bAny:$Pg, GPR64sp:$Rn, immtype:$imm4), + asm, "\t$Zt, $Pg/z, [$Rn, $imm4, mul vl]", + "", + []>, Sched<[]> { + bits<5> Zt; + bits<3> Pg; + bits<5> Rn; + bits<4> imm4; + let Inst{31-25} = 0b1010010; + let Inst{24-23} = sz; + let Inst{22-21} = nregs; + let Inst{20} = 0; + let Inst{19-16} = imm4; + let Inst{15-13} = 0b111; + let Inst{12-10} = Pg; + let Inst{9-5} = Rn; + let Inst{4-0} = Zt; + + let mayLoad = 1; +} + +multiclass sve_mem_eld_si sz, bits<2> nregs, RegisterOperand VecList, + string asm, Operand immtype> { + def NAME : sve_mem_eld_si; + + def : InstAlias(NAME) VecList:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, 0), 1>; +} Index: test/MC/AArch64/SVE/ld2b-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2b-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-16, 14]. + +ld2b {z12.b, z13.b}, p4/z, [x12, #-18, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2b {z12.b, z13.b}, p4/z, [x12, #-18, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b {z7.b, z8.b}, p3/z, [x1, #16, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2b {z7.b, z8.b}, p3/z, [x1, #16, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of two. + +ld2b {z12.b, z13.b}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2b {z12.b, z13.b}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b {z7.b, z8.b}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2b {z7.b, z8.b}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld2b {z2.b, z3.b}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld2b {z2.b, z3.b}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld2b { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld2b { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b { z0.b, z1.b, z2.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2b { z0.b, z1.b, z2.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b { z0.b, z1.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld2b { z0.b, z1.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b { z0.b, z2.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld2b { z0.b, z2.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2b { v0.2d, v1.2d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2b { v0.2d, v1.2d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/ld2b.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2b.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld2b { z0.b, z1.b }, p0/z, [x0] +// CHECK-INST: ld2b { z0.b, z1.b }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0x20,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 20 a4 + +ld2b { z23.b, z24.b }, p3/z, [x13, #-16, mul vl] +// CHECK-INST: ld2b { z23.b, z24.b }, p3/z, [x13, #-16, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0x28,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed 28 a4 + +ld2b { z21.b, z22.b }, p5/z, [x10, #10, mul vl] +// CHECK-INST: ld2b { z21.b, z22.b }, p5/z, [x10, #10, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0x25,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 25 a4 Index: test/MC/AArch64/SVE/ld2d-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2d-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-16, 14]. + +ld2d {z12.d, z13.d}, p4/z, [x12, #-18, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2d {z12.d, z13.d}, p4/z, [x12, #-18, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d {z7.d, z8.d}, p3/z, [x1, #16, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2d {z7.d, z8.d}, p3/z, [x1, #16, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of two. + +ld2d {z12.d, z13.d}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2d {z12.d, z13.d}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d {z7.d, z8.d}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2d {z7.d, z8.d}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld2d {z2.d, z3.d}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld2d {z2.d, z3.d}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld2d { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld2d { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d { z0.d, z1.d, z2.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2d { z0.d, z1.d, z2.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d { z0.d, z1.b }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld2d { z0.d, z1.b }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d { z0.d, z2.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld2d { z0.d, z2.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2d { v0.2d, v1.2d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2d { v0.2d, v1.2d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/ld2d.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2d.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld2d { z0.d, z1.d }, p0/z, [x0] +// CHECK-INST: ld2d { z0.d, z1.d }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0xa0,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 a0 a5 + +ld2d { z23.d, z24.d }, p3/z, [x13, #-16, mul vl] +// CHECK-INST: ld2d { z23.d, z24.d }, p3/z, [x13, #-16, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0xa8,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed a8 a5 + +ld2d { z21.d, z22.d }, p5/z, [x10, #10, mul vl] +// CHECK-INST: ld2d { z21.d, z22.d }, p5/z, [x10, #10, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0xa5,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 a5 a5 Index: test/MC/AArch64/SVE/ld2h-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2h-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-16, 14]. + +ld2h {z12.h, z13.h}, p4/z, [x12, #-18, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2h {z12.h, z13.h}, p4/z, [x12, #-18, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h {z7.h, z8.h}, p3/z, [x1, #16, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2h {z7.h, z8.h}, p3/z, [x1, #16, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of two. + +ld2h {z12.h, z13.h}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2h {z12.h, z13.h}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h {z7.h, z8.h}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2h {z7.h, z8.h}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld2h {z2.h, z3.h}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld2h {z2.h, z3.h}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld2h { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld2h { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h { z0.h, z1.h, z2.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2h { z0.h, z1.h, z2.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h { z0.h, z1.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld2h { z0.h, z1.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h { z0.h, z2.h }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld2h { z0.h, z2.h }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2h { v0.2d, v1.2d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2h { v0.2d, v1.2d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/ld2h.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2h.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld2h { z0.h, z1.h }, p0/z, [x0] +// CHECK-INST: ld2h { z0.h, z1.h }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0xa0,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 a0 a4 + +ld2h { z23.h, z24.h }, p3/z, [x13, #-16, mul vl] +// CHECK-INST: ld2h { z23.h, z24.h }, p3/z, [x13, #-16, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0xa8,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed a8 a4 + +ld2h { z21.h, z22.h }, p5/z, [x10, #10, mul vl] +// CHECK-INST: ld2h { z21.h, z22.h }, p5/z, [x10, #10, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0xa5,0xa4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 a5 a4 Index: test/MC/AArch64/SVE/ld2w-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2w-diagnostics.s @@ -0,0 +1,67 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// --------------------------------------------------------------------------// +// Immediate out of lower bound [-16, 14]. + +ld2w {z12.s, z13.s}, p4/z, [x12, #-18, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2w {z12.s, z13.s}, p4/z, [x12, #-18, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w {z7.s, z8.s}, p3/z, [x1, #16, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2w {z7.s, z8.s}, p3/z, [x1, #16, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Immediate not a multiple of two. + +ld2w {z12.s, z13.s}, p4/z, [x12, #-7, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2w {z12.s, z13.s}, p4/z, [x12, #-7, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w {z7.s, z8.s}, p3/z, [x1, #5, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be a multiple of 2 in range [-16, 14]. +// CHECK-NEXT: ld2w {z7.s, z8.s}, p3/z, [x1, #5, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// error: restricted predicate has range [0, 7]. + +ld2w {z2.s, z3.s}, p8/z, [x15, #10, MUL VL] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: ld2w {z2.s, z3.s}, p8/z, [x15, #10, MUL VL] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid vector list. + +ld2w { }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector register expected +// CHECK-NEXT: ld2w { }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w { z0.s, z1.s, z2.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2w { z0.s, z1.s, z2.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w { z0.s, z1.d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: ld2w { z0.s, z1.d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w { z0.s, z2.s }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: ld2w { z0.s, z2.s }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ld2w { v0.2d, v1.2d }, p0/z, [x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand +// CHECK-NEXT: ld2w { v0.2d, v1.2d }, p0/z, [x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/ld2w.s =================================================================== --- /dev/null +++ test/MC/AArch64/SVE/ld2w.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ld2w { z0.s, z1.s }, p0/z, [x0] +// CHECK-INST: ld2w { z0.s, z1.s }, p0/z, [x0] +// CHECK-ENCODING: [0x00,0xe0,0x20,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 e0 20 a5 + +ld2w { z23.s, z24.s }, p3/z, [x13, #-16, mul vl] +// CHECK-INST: ld2w { z23.s, z24.s }, p3/z, [x13, #-16, mul vl] +// CHECK-ENCODING: [0xb7,0xed,0x28,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: b7 ed 28 a5 + +ld2w { z21.s, z22.s }, p5/z, [x10, #10, mul vl] +// CHECK-INST: ld2w { z21.s, z22.s }, p5/z, [x10, #10, mul vl] +// CHECK-ENCODING: [0x55,0xf5,0x25,0xa5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 55 f5 25 a5