Index: lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64SVEInstrInfo.td +++ lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -230,6 +230,18 @@ defm ST1W_D_IMM : sve_mem_cst_si<0b10, 0b11, "st1w", Z_d, ZPR64>; defm ST1D_IMM : sve_mem_cst_si<0b11, 0b11, "st1d", Z_d, ZPR64>; + // contiguous store with reg+reg addressing. + defm ST1B : sve_mem_cst_ss<0b0000, "st1b", Z_b, ZPR8, GPR64NoXZRshifted8>; + defm ST1B_H : sve_mem_cst_ss<0b0001, "st1b", Z_h, ZPR16, GPR64NoXZRshifted8>; + defm ST1B_S : sve_mem_cst_ss<0b0010, "st1b", Z_s, ZPR32, GPR64NoXZRshifted8>; + defm ST1B_D : sve_mem_cst_ss<0b0011, "st1b", Z_d, ZPR64, GPR64NoXZRshifted8>; + defm ST1H : sve_mem_cst_ss<0b0101, "st1h", Z_h, ZPR16, GPR64NoXZRshifted16>; + defm ST1H_S : sve_mem_cst_ss<0b0110, "st1h", Z_s, ZPR32, GPR64NoXZRshifted16>; + defm ST1H_D : sve_mem_cst_ss<0b0111, "st1h", Z_d, ZPR64, GPR64NoXZRshifted16>; + defm ST1W : sve_mem_cst_ss<0b1010, "st1w", Z_s, ZPR32, GPR64NoXZRshifted32>; + defm ST1W_D : sve_mem_cst_ss<0b1011, "st1w", Z_d, ZPR64, GPR64NoXZRshifted32>; + defm ST1D : sve_mem_cst_ss<0b1111, "st1d", Z_d, ZPR64, GPR64NoXZRshifted64>; + // ST{2,3,4}{B,H,W,D} with immediate defm ST2B_IMM : sve_mem_est_si<0b00, 0b01, ZZ_b, "st2b", simm4Scale2MulVl>; defm ST3B_IMM : sve_mem_est_si<0b00, 0b10, ZZZ_b, "st3b", simm4Scale3MulVl>; Index: lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- lib/Target/AArch64/SVEInstrFormats.td +++ lib/Target/AArch64/SVEInstrFormats.td @@ -602,6 +602,36 @@ (!cast(NAME) VecList:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, 0), 1>; } +class sve_mem_cst_ss_base dtype, string asm, + RegisterOperand listty, RegisterOperand gprty> +: I<(outs), (ins listty:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, gprty:$Rm), + asm, "\t$Zt, $Pg, [$Rn, $Rm]", + "", + []>, Sched<[]> { + bits<3> Pg; + bits<5> Rm; + bits<5> Rn; + bits<5> Zt; + let Inst{31-25} = 0b1110010; + let Inst{24-21} = dtype; + let Inst{20-16} = Rm; + let Inst{15-13} = 0b010; + let Inst{12-10} = Pg; + let Inst{9-5} = Rn; + let Inst{4-0} = Zt; + + let mayStore = 1; +} + +multiclass sve_mem_cst_ss dtype, string asm, + RegisterOperand listty, ZPRRegOp zprty, + RegisterOperand gprty> { + def NAME : sve_mem_cst_ss_base; + + def : InstAlias(NAME) zprty:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, gprty:$Rm), 0>; +} + //===----------------------------------------------------------------------===// // SVE Permute - Predicates Group //===----------------------------------------------------------------------===// @@ -958,4 +988,4 @@ (!cast(NAME # _IMM_REAL) ZPR64:$Zt, PPR3bAny:$Pg, ZPR64:$Zn, imm_ty:$imm5), 0>; def : InstAlias(NAME # _IMM_REAL) Z_d:$Zt, PPR3bAny:$Pg, ZPR64:$Zn, 0), 1>; -} \ No newline at end of file +} Index: test/MC/AArch64/SVE/st1b-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/st1b-diagnostics.s +++ test/MC/AArch64/SVE/st1b-diagnostics.s @@ -83,3 +83,27 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand // CHECK-NEXT: st1b { v0.16b }, p0, [x0] // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid scalar + scalar addressing modes + +st1b z0.b, p0, [x0, xzr] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 without shift +// CHECK-NEXT: st1b z0.b, p0, [x0, xzr] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1b z0.b, p0, [x0, x0, lsl #1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 without shift +// CHECK-NEXT: st1b z0.b, p0, [x0, x0, lsl #1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1b z0.b, p0, [x0, w0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 without shift +// CHECK-NEXT: st1b z0.b, p0, [x0, w0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1b z0.b, p0, [x0, w0, uxtw] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 without shift +// CHECK-NEXT: st1b z0.b, p0, [x0, w0, uxtw] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/st1b.s =================================================================== --- test/MC/AArch64/SVE/st1b.s +++ test/MC/AArch64/SVE/st1b.s @@ -102,3 +102,27 @@ // CHECK-ENCODING: [0x55,0xf5,0x65,0xe4] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 55 f5 65 e4 + +st1b { z0.b }, p0, [x0, x0] +// CHECK-INST: st1b { z0.b }, p0, [x0, x0] +// CHECK-ENCODING: [0x00,0x40,0x00,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 00 e4 + +st1b { z0.h }, p0, [x0, x0] +// CHECK-INST: st1b { z0.h }, p0, [x0, x0] +// CHECK-ENCODING: [0x00,0x40,0x20,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 20 e4 + +st1b { z0.s }, p0, [x0, x0] +// CHECK-INST: st1b { z0.s }, p0, [x0, x0] +// CHECK-ENCODING: [0x00,0x40,0x40,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 40 e4 + +st1b { z0.d }, p0, [x0, x0] +// CHECK-INST: st1b { z0.d }, p0, [x0, x0] +// CHECK-ENCODING: [0x00,0x40,0x60,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 60 e4 Index: test/MC/AArch64/SVE/st1d-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/st1d-diagnostics.s +++ test/MC/AArch64/SVE/st1d-diagnostics.s @@ -39,3 +39,32 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand // CHECK-NEXT: st1d { v0.2d }, p0, [x0] // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid scalar + scalar addressing modes + +st1d z0.d, p0, [x0, x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #3' +// CHECK-NEXT: st1d z0.d, p0, [x0, x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1d z0.d, p0, [x0, xzr] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #3' +// CHECK-NEXT: st1d z0.d, p0, [x0, xzr] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1d z0.d, p0, [x0, x0, lsl #2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #3' +// CHECK-NEXT: st1d z0.d, p0, [x0, x0, lsl #2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1d z0.d, p0, [x0, w0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #3' +// CHECK-NEXT: st1d z0.d, p0, [x0, w0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1d z0.d, p0, [x0, w0, uxtw] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #3' +// CHECK-NEXT: st1d z0.d, p0, [x0, w0, uxtw] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/st1d.s =================================================================== --- test/MC/AArch64/SVE/st1d.s +++ test/MC/AArch64/SVE/st1d.s @@ -30,3 +30,9 @@ // CHECK-ENCODING: [0x55,0xf5,0xe5,0xe5] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 55 f5 e5 e5 + +st1d { z0.d }, p0, [x0, x0, lsl #3] +// CHECK-INST: st1d { z0.d }, p0, [x0, x0, lsl #3] +// CHECK-ENCODING: [0x00,0x40,0xe0,0xe5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 e0 e5 Index: test/MC/AArch64/SVE/st1h-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/st1h-diagnostics.s +++ test/MC/AArch64/SVE/st1h-diagnostics.s @@ -68,3 +68,32 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand // CHECK-NEXT: st1h { v0.8h }, p0, [x0] // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid scalar + scalar addressing modes + +st1h z0.h, p0, [x0, x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #1' +// CHECK-NEXT: st1h z0.h, p0, [x0, x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1h z0.h, p0, [x0, xzr] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #1' +// CHECK-NEXT: st1h z0.h, p0, [x0, xzr] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1h z0.h, p0, [x0, x0, lsl #2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #1' +// CHECK-NEXT: st1h z0.h, p0, [x0, x0, lsl #2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1h z0.h, p0, [x0, w0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #1' +// CHECK-NEXT: st1h z0.h, p0, [x0, w0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1h z0.h, p0, [x0, w0, uxtw] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #1' +// CHECK-NEXT: st1h z0.h, p0, [x0, w0, uxtw] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/st1h.s =================================================================== --- test/MC/AArch64/SVE/st1h.s +++ test/MC/AArch64/SVE/st1h.s @@ -78,3 +78,21 @@ // CHECK-ENCODING: [0xff,0xff,0xef,0xe4] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff ff ef e4 + +st1h { z0.h }, p0, [x0, x0, lsl #1] +// CHECK-INST: st1h { z0.h }, p0, [x0, x0, lsl #1] +// CHECK-ENCODING: [0x00,0x40,0xa0,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 a0 e4 + +st1h { z0.s }, p0, [x0, x0, lsl #1] +// CHECK-INST: st1h { z0.s }, p0, [x0, x0, lsl #1] +// CHECK-ENCODING: [0x00,0x40,0xc0,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 c0 e4 + +st1h { z0.d }, p0, [x0, x0, lsl #1] +// CHECK-INST: st1h { z0.d }, p0, [x0, x0, lsl #1] +// CHECK-ENCODING: [0x00,0x40,0xe0,0xe4] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 e0 e4 Index: test/MC/AArch64/SVE/st1w-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/st1w-diagnostics.s +++ test/MC/AArch64/SVE/st1w-diagnostics.s @@ -56,3 +56,32 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand // CHECK-NEXT: st1w { v0.4s }, p0, [x0] // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid scalar + scalar addressing modes + +st1w z0.s, p0, [x0, x0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #2' +// CHECK-NEXT: st1w z0.s, p0, [x0, x0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1w z0.s, p0, [x0, xzr] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #2' +// CHECK-NEXT: st1w z0.s, p0, [x0, xzr] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1w z0.s, p0, [x0, x0, lsl #3] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #2' +// CHECK-NEXT: st1w z0.s, p0, [x0, x0, lsl #3] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1w z0.s, p0, [x0, w0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #2' +// CHECK-NEXT: st1w z0.s, p0, [x0, w0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +st1w z0.s, p0, [x0, w0, uxtw] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: register must be x0..x30 with required shift 'lsl #2' +// CHECK-NEXT: st1w z0.s, p0, [x0, w0, uxtw] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/st1w.s =================================================================== --- test/MC/AArch64/SVE/st1w.s +++ test/MC/AArch64/SVE/st1w.s @@ -54,3 +54,15 @@ // CHECK-ENCODING: [0x55,0xf5,0x65,0xe5] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 55 f5 65 e5 + +st1w { z0.s }, p0, [x0, x0, lsl #2] +// CHECK-INST: st1w { z0.s }, p0, [x0, x0, lsl #2] +// CHECK-ENCODING: [0x00,0x40,0x40,0xe5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 40 e5 + +st1w { z0.d }, p0, [x0, x0, lsl #2] +// CHECK-INST: st1w { z0.d }, p0, [x0, x0, lsl #2] +// CHECK-ENCODING: [0x00,0x40,0x60,0xe5] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 40 60 e5