• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include "assembler-aarch64.h"
28 
29 namespace vixl {
30 namespace aarch64 {
31 
ResolveSVEImm8Shift(int * imm8,int * shift)32 void Assembler::ResolveSVEImm8Shift(int* imm8, int* shift) {
33   if (*shift < 0) {
34     VIXL_ASSERT(*shift == -1);
35     // Derive the shift amount from the immediate.
36     if (IsInt8(*imm8)) {
37       *shift = 0;
38     } else if ((*imm8 % 256) == 0) {
39       *imm8 /= 256;
40       *shift = 8;
41     }
42   }
43 
44   VIXL_ASSERT(IsInt8(*imm8));
45   VIXL_ASSERT((*shift == 0) || (*shift == 8));
46 }
47 
48 // SVEAddressGeneration.
49 
adr(const ZRegister & zd,const SVEMemOperand & addr)50 void Assembler::adr(const ZRegister& zd, const SVEMemOperand& addr) {
51   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
52   VIXL_ASSERT(addr.IsVectorPlusVector());
53   VIXL_ASSERT(
54       AreSameLaneSize(zd, addr.GetVectorBase(), addr.GetVectorOffset()));
55 
56   int lane_size = zd.GetLaneSizeInBits();
57   VIXL_ASSERT((lane_size == kSRegSize) || (lane_size == kDRegSize));
58 
59   int shift_amount = addr.GetShiftAmount();
60   VIXL_ASSERT((shift_amount >= 0) && (shift_amount <= 3));
61 
62   Instr op = 0xffffffff;
63   Instr msz = shift_amount << 10;
64   SVEOffsetModifier mod = addr.GetOffsetModifier();
65   switch (mod) {
66     case SVE_UXTW:
67       VIXL_ASSERT(lane_size == kDRegSize);
68       op = ADR_z_az_d_u32_scaled;
69       break;
70     case SVE_SXTW:
71       VIXL_ASSERT(lane_size == kDRegSize);
72       op = ADR_z_az_d_s32_scaled;
73       break;
74     case SVE_LSL:
75     case NO_SVE_OFFSET_MODIFIER:
76       op = (lane_size == kSRegSize) ? ADR_z_az_s_same_scaled
77                                     : ADR_z_az_d_same_scaled;
78       break;
79     default:
80       VIXL_UNIMPLEMENTED();
81   }
82   Emit(op | msz | Rd(zd) | Rn(addr.GetVectorBase()) |
83        Rm(addr.GetVectorOffset()));
84 }
85 
SVELogicalImmediate(const ZRegister & zdn,uint64_t imm,Instr op)86 void Assembler::SVELogicalImmediate(const ZRegister& zdn,
87                                     uint64_t imm,
88                                     Instr op) {
89   unsigned bit_n, imm_s, imm_r;
90   unsigned lane_size = zdn.GetLaneSizeInBits();
91   // Check that the immediate can be encoded in the instruction.
92   if (IsImmLogical(imm, lane_size, &bit_n, &imm_s, &imm_r)) {
93     Emit(op | Rd(zdn) | SVEBitN(bit_n) | SVEImmRotate(imm_r, lane_size) |
94          SVEImmSetBits(imm_s, lane_size));
95   } else {
96     VIXL_UNREACHABLE();
97   }
98 }
99 
and_(const ZRegister & zd,const ZRegister & zn,uint64_t imm)100 void Assembler::and_(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
101   USE(zn);
102   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
103   VIXL_ASSERT(zd.Is(zn));
104   SVELogicalImmediate(zd, imm, AND_z_zi);
105 }
106 
dupm(const ZRegister & zd,uint64_t imm)107 void Assembler::dupm(const ZRegister& zd, uint64_t imm) {
108   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
109   // DUPM_z_i is an SVEBroadcastBitmaskImmOp, but its encoding and constraints
110   // are similar enough to SVEBitwiseLogicalWithImm_UnpredicatedOp, that we can
111   // use the logical immediate encoder to get the correct behaviour.
112   SVELogicalImmediate(zd, imm, DUPM_z_i);
113 }
114 
eor(const ZRegister & zd,const ZRegister & zn,uint64_t imm)115 void Assembler::eor(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
116   USE(zn);
117   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
118   VIXL_ASSERT(zd.Is(zn));
119   SVELogicalImmediate(zd, imm, EOR_z_zi);
120 }
121 
orr(const ZRegister & zd,const ZRegister & zn,uint64_t imm)122 void Assembler::orr(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
123   USE(zn);
124   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
125   VIXL_ASSERT(zd.Is(zn));
126   SVELogicalImmediate(zd, imm, ORR_z_zi);
127 }
128 
129 // SVEBitwiseLogicalUnpredicated.
and_(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)130 void Assembler::and_(const ZRegister& zd,
131                      const ZRegister& zn,
132                      const ZRegister& zm) {
133   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
134   VIXL_ASSERT(zd.IsLaneSizeD());
135   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
136   Emit(AND_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
137 }
138 
bic(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)139 void Assembler::bic(const ZRegister& zd,
140                     const ZRegister& zn,
141                     const ZRegister& zm) {
142   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
143   VIXL_ASSERT(zd.IsLaneSizeD());
144   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
145   Emit(BIC_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
146 }
147 
eor(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)148 void Assembler::eor(const ZRegister& zd,
149                     const ZRegister& zn,
150                     const ZRegister& zm) {
151   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
152   VIXL_ASSERT(zd.IsLaneSizeD());
153   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
154   Emit(EOR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
155 }
156 
orr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)157 void Assembler::orr(const ZRegister& zd,
158                     const ZRegister& zn,
159                     const ZRegister& zm) {
160   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
161   VIXL_ASSERT(zd.IsLaneSizeD());
162   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
163   Emit(ORR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
164 }
165 
166 // SVEBitwiseShiftPredicated.
167 
SVEBitwiseShiftImmediatePred(const ZRegister & zdn,const PRegisterM & pg,Instr encoded_imm_and_tsz,Instr op)168 void Assembler::SVEBitwiseShiftImmediatePred(const ZRegister& zdn,
169                                              const PRegisterM& pg,
170                                              Instr encoded_imm_and_tsz,
171                                              Instr op) {
172   Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)
173                        << 5;
174   Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;
175   Emit(op | tszh | tszl_and_imm | PgLow8(pg) | Rd(zdn));
176 }
177 
asr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)178 void Assembler::asr(const ZRegister& zd,
179                     const PRegisterM& pg,
180                     const ZRegister& zn,
181                     int shift) {
182   // ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
183   //  0000 0100 ..00 0000 100. .... .... ....
184   //  tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 0 | Pg<12:10> |
185   //  tszl<9:8> | imm3<7:5> | Zdn<4:0>
186 
187   USE(zn);
188   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
189   VIXL_ASSERT(zd.Is(zn));
190   Instr encoded_imm =
191       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
192   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASR_z_p_zi);
193 }
194 
asr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)195 void Assembler::asr(const ZRegister& zd,
196                     const PRegisterM& pg,
197                     const ZRegister& zn,
198                     const ZRegister& zm) {
199   // ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
200   //  0000 0100 ..01 1000 100. .... .... ....
201   //  size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |
202   //  Zdn<4:0>
203 
204   USE(zn);
205   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
206   VIXL_ASSERT(zd.Is(zn));
207   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
208               ((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
209                (zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
210   Instr op = ASR_z_p_zw;
211   if (AreSameLaneSize(zd, zn, zm)) {
212     op = ASR_z_p_zz;
213   }
214   Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
215 }
216 
asrd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)217 void Assembler::asrd(const ZRegister& zd,
218                      const PRegisterM& pg,
219                      const ZRegister& zn,
220                      int shift) {
221   // ASRD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
222   //  0000 0100 ..00 0100 100. .... .... ....
223   //  tszh<23:22> | opc<19:18> = 01 | L<17> = 0 | U<16> = 0 | Pg<12:10> |
224   //  tszl<9:8> | imm3<7:5> | Zdn<4:0>
225 
226   USE(zn);
227   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
228   VIXL_ASSERT(zd.Is(zn));
229 
230   Instr encoded_imm =
231       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
232   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASRD_z_p_zi);
233 }
234 
asrr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)235 void Assembler::asrr(const ZRegister& zd,
236                      const PRegisterM& pg,
237                      const ZRegister& zn,
238                      const ZRegister& zm) {
239   // ASRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
240   //  0000 0100 ..01 0100 100. .... .... ....
241   //  size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |
242   //  Zdn<4:0>
243 
244   USE(zn);
245   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
246   VIXL_ASSERT(zd.Is(zn));
247   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
248 
249   Emit(ASRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
250 }
251 
lsl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)252 void Assembler::lsl(const ZRegister& zd,
253                     const PRegisterM& pg,
254                     const ZRegister& zn,
255                     int shift) {
256   // LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
257   //  0000 0100 ..00 0011 100. .... .... ....
258   //  tszh<23:22> | opc<19:18> = 00 | L<17> = 1 | U<16> = 1 | Pg<12:10> |
259   //  tszl<9:8> | imm3<7:5> | Zdn<4:0>
260 
261   USE(zn);
262   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
263   VIXL_ASSERT(zd.Is(zn));
264 
265   Instr encoded_imm =
266       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
267   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSL_z_p_zi);
268 }
269 
lsl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)270 void Assembler::lsl(const ZRegister& zd,
271                     const PRegisterM& pg,
272                     const ZRegister& zn,
273                     const ZRegister& zm) {
274   // LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
275   //  0000 0100 ..01 1011 100. .... .... ....
276   //  size<23:22> | R<18> = 0 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
277   //  Zdn<4:0>
278 
279   USE(zn);
280   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
281   VIXL_ASSERT(zd.Is(zn));
282   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
283               ((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
284                (zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
285   Instr op = LSL_z_p_zw;
286   if (AreSameLaneSize(zd, zn, zm)) {
287     op = LSL_z_p_zz;
288   }
289   Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
290 }
291 
lslr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)292 void Assembler::lslr(const ZRegister& zd,
293                      const PRegisterM& pg,
294                      const ZRegister& zn,
295                      const ZRegister& zm) {
296   // LSLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
297   //  0000 0100 ..01 0111 100. .... .... ....
298   //  size<23:22> | R<18> = 1 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
299   //  Zdn<4:0>
300 
301   USE(zn);
302   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
303   VIXL_ASSERT(zd.Is(zn));
304   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
305 
306   Emit(LSLR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
307 }
308 
lsr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)309 void Assembler::lsr(const ZRegister& zd,
310                     const PRegisterM& pg,
311                     const ZRegister& zn,
312                     int shift) {
313   // LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
314   //  0000 0100 ..00 0001 100. .... .... ....
315   //  tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 1 | Pg<12:10> |
316   //  tszl<9:8> | imm3<7:5> | Zdn<4:0>
317 
318   USE(zn);
319   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
320   VIXL_ASSERT(zd.Is(zn));
321 
322   Instr encoded_imm =
323       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
324   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSR_z_p_zi);
325 }
326 
lsr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)327 void Assembler::lsr(const ZRegister& zd,
328                     const PRegisterM& pg,
329                     const ZRegister& zn,
330                     const ZRegister& zm) {
331   // LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
332   //  0000 0100 ..01 1001 100. .... .... ....
333   //  size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
334   //  Zdn<4:0>
335 
336   USE(zn);
337   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
338   VIXL_ASSERT(zd.Is(zn));
339   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
340               ((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
341                (zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
342   Instr op = LSR_z_p_zw;
343   if (AreSameLaneSize(zd, zn, zm)) {
344     op = LSR_z_p_zz;
345   }
346   Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
347 }
348 
lsrr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)349 void Assembler::lsrr(const ZRegister& zd,
350                      const PRegisterM& pg,
351                      const ZRegister& zn,
352                      const ZRegister& zm) {
353   // LSRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
354   //  0000 0100 ..01 0101 100. .... .... ....
355   //  size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
356   //  Zdn<4:0>
357 
358   USE(zn);
359   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
360   VIXL_ASSERT(zd.Is(zn));
361   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
362 
363   Emit(LSRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
364 }
365 
366 // SVEBitwiseShiftUnpredicated.
367 
EncodeSVEShiftLeftImmediate(int shift,int lane_size_in_bits)368 Instr Assembler::EncodeSVEShiftLeftImmediate(int shift, int lane_size_in_bits) {
369   VIXL_ASSERT((shift >= 0) && (shift < lane_size_in_bits));
370   return lane_size_in_bits + shift;
371 }
372 
EncodeSVEShiftRightImmediate(int shift,int lane_size_in_bits)373 Instr Assembler::EncodeSVEShiftRightImmediate(int shift,
374                                               int lane_size_in_bits) {
375   VIXL_ASSERT((shift > 0) && (shift <= lane_size_in_bits));
376   return (2 * lane_size_in_bits) - shift;
377 }
378 
SVEBitwiseShiftImmediate(const ZRegister & zd,const ZRegister & zn,Instr encoded_imm_and_tsz,Instr op)379 void Assembler::SVEBitwiseShiftImmediate(const ZRegister& zd,
380                                          const ZRegister& zn,
381                                          Instr encoded_imm_and_tsz,
382                                          Instr op) {
383   Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)
384                        << 16;
385   Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;
386   Emit(op | tszh | tszl_and_imm | Rd(zd) | Rn(zn));
387 }
388 
asr(const ZRegister & zd,const ZRegister & zn,int shift)389 void Assembler::asr(const ZRegister& zd, const ZRegister& zn, int shift) {
390   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
391   VIXL_ASSERT(AreSameLaneSize(zd, zn));
392   Instr encoded_imm =
393       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
394   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, ASR_z_zi);
395 }
396 
asr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)397 void Assembler::asr(const ZRegister& zd,
398                     const ZRegister& zn,
399                     const ZRegister& zm) {
400   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
401   VIXL_ASSERT(AreSameLaneSize(zd, zn));
402   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
403 
404   Emit(ASR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
405 }
406 
lsl(const ZRegister & zd,const ZRegister & zn,int shift)407 void Assembler::lsl(const ZRegister& zd, const ZRegister& zn, int shift) {
408   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
409   Instr encoded_imm =
410       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
411   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSL_z_zi);
412 }
413 
lsl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)414 void Assembler::lsl(const ZRegister& zd,
415                     const ZRegister& zn,
416                     const ZRegister& zm) {
417   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
418   VIXL_ASSERT(AreSameLaneSize(zd, zn));
419   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
420 
421   Emit(LSL_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
422 }
423 
lsr(const ZRegister & zd,const ZRegister & zn,int shift)424 void Assembler::lsr(const ZRegister& zd, const ZRegister& zn, int shift) {
425   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
426   Instr encoded_imm =
427       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
428   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSR_z_zi);
429 }
430 
lsr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)431 void Assembler::lsr(const ZRegister& zd,
432                     const ZRegister& zn,
433                     const ZRegister& zm) {
434   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
435   VIXL_ASSERT(AreSameLaneSize(zd, zn));
436   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
437 
438   Emit(LSR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
439 }
440 
441 // SVEElementCount.
442 
443 #define VIXL_SVE_INC_DEC_LIST(V) \
444   V(cntb, CNTB_r_s)              \
445   V(cnth, CNTH_r_s)              \
446   V(cntw, CNTW_r_s)              \
447   V(cntd, CNTD_r_s)              \
448   V(decb, DECB_r_rs)             \
449   V(dech, DECH_r_rs)             \
450   V(decw, DECW_r_rs)             \
451   V(decd, DECD_r_rs)             \
452   V(incb, INCB_r_rs)             \
453   V(inch, INCH_r_rs)             \
454   V(incw, INCW_r_rs)             \
455   V(incd, INCD_r_rs)             \
456   V(sqdecb, SQDECB_r_rs_x)       \
457   V(sqdech, SQDECH_r_rs_x)       \
458   V(sqdecw, SQDECW_r_rs_x)       \
459   V(sqdecd, SQDECD_r_rs_x)       \
460   V(sqincb, SQINCB_r_rs_x)       \
461   V(sqinch, SQINCH_r_rs_x)       \
462   V(sqincw, SQINCW_r_rs_x)       \
463   V(sqincd, SQINCD_r_rs_x)
464 
465 #define VIXL_DEFINE_ASM_FUNC(FN, OP)                                     \
466   void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \
467     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                              \
468     VIXL_ASSERT(rdn.IsX());                                              \
469     Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) |             \
470          ImmUnsignedField<19, 16>(multiplier - 1));                      \
471   }
472 VIXL_SVE_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)
473 #undef VIXL_DEFINE_ASM_FUNC
474 
475 #define VIXL_SVE_UQINC_UQDEC_LIST(V)                      \
476   V(uqdecb, (rdn.IsX() ? UQDECB_r_rs_x : UQDECB_r_rs_uw)) \
477   V(uqdech, (rdn.IsX() ? UQDECH_r_rs_x : UQDECH_r_rs_uw)) \
478   V(uqdecw, (rdn.IsX() ? UQDECW_r_rs_x : UQDECW_r_rs_uw)) \
479   V(uqdecd, (rdn.IsX() ? UQDECD_r_rs_x : UQDECD_r_rs_uw)) \
480   V(uqincb, (rdn.IsX() ? UQINCB_r_rs_x : UQINCB_r_rs_uw)) \
481   V(uqinch, (rdn.IsX() ? UQINCH_r_rs_x : UQINCH_r_rs_uw)) \
482   V(uqincw, (rdn.IsX() ? UQINCW_r_rs_x : UQINCW_r_rs_uw)) \
483   V(uqincd, (rdn.IsX() ? UQINCD_r_rs_x : UQINCD_r_rs_uw))
484 
485 #define VIXL_DEFINE_ASM_FUNC(FN, OP)                                     \
486   void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \
487     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                              \
488     Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) |             \
489          ImmUnsignedField<19, 16>(multiplier - 1));                      \
490   }
VIXL_SVE_UQINC_UQDEC_LIST(VIXL_DEFINE_ASM_FUNC)491 VIXL_SVE_UQINC_UQDEC_LIST(VIXL_DEFINE_ASM_FUNC)
492 #undef VIXL_DEFINE_ASM_FUNC
493 
494 #define VIXL_SVE_SQX_INC_DEC_LIST(V) \
495   V(sqdecb, SQDECB)                  \
496   V(sqdech, SQDECH)                  \
497   V(sqdecw, SQDECW)                  \
498   V(sqdecd, SQDECD)                  \
499   V(sqincb, SQINCB)                  \
500   V(sqinch, SQINCH)                  \
501   V(sqincw, SQINCW)                  \
502   V(sqincd, SQINCD)
503 
504 #define VIXL_DEFINE_ASM_FUNC(FN, OP)                                  \
505   void Assembler::FN(const Register& xd,                              \
506                      const Register& wn,                              \
507                      int pattern,                                     \
508                      int multiplier) {                                \
509     USE(wn);                                                          \
510     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                           \
511     VIXL_ASSERT(wn.IsW() && xd.Is(wn.X()));                           \
512     Emit(OP##_r_rs_sx | Rd(xd) | ImmSVEPredicateConstraint(pattern) | \
513          ImmUnsignedField<19, 16>(multiplier - 1));                   \
514   }
515 VIXL_SVE_SQX_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)
516 #undef VIXL_DEFINE_ASM_FUNC
517 
518 #define VIXL_SVE_INC_DEC_VEC_LIST(V) \
519   V(dech, DEC, H)                    \
520   V(decw, DEC, W)                    \
521   V(decd, DEC, D)                    \
522   V(inch, INC, H)                    \
523   V(incw, INC, W)                    \
524   V(incd, INC, D)                    \
525   V(sqdech, SQDEC, H)                \
526   V(sqdecw, SQDEC, W)                \
527   V(sqdecd, SQDEC, D)                \
528   V(sqinch, SQINC, H)                \
529   V(sqincw, SQINC, W)                \
530   V(sqincd, SQINC, D)                \
531   V(uqdech, UQDEC, H)                \
532   V(uqdecw, UQDEC, W)                \
533   V(uqdecd, UQDEC, D)                \
534   V(uqinch, UQINC, H)                \
535   V(uqincw, UQINC, W)                \
536   V(uqincd, UQINC, D)
537 
538 #define VIXL_DEFINE_ASM_FUNC(FN, OP, T)                                   \
539   void Assembler::FN(const ZRegister& zdn, int pattern, int multiplier) { \
540     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                               \
541     VIXL_ASSERT(zdn.GetLaneSizeInBytes() == k##T##RegSizeInBytes);        \
542     Emit(OP##T##_z_zs | Rd(zdn) | ImmSVEPredicateConstraint(pattern) |    \
543          ImmUnsignedField<19, 16>(multiplier - 1));                       \
544   }
545 VIXL_SVE_INC_DEC_VEC_LIST(VIXL_DEFINE_ASM_FUNC)
546 #undef VIXL_DEFINE_ASM_FUNC
547 
548 // SVEFPAccumulatingReduction.
549 
550 void Assembler::fadda(const VRegister& vd,
551                       const PRegister& pg,
552                       const VRegister& vn,
553                       const ZRegister& zm) {
554   // FADDA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
555   //  0110 0101 ..01 1000 001. .... .... ....
556   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
557 
558   USE(vn);
559   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
560   VIXL_ASSERT(vd.Is(vn));
561   VIXL_ASSERT(vd.IsScalar());
562   VIXL_ASSERT(zm.GetLaneSizeInBytes() != kBRegSizeInBytes);
563   VIXL_ASSERT(AreSameLaneSize(zm, vd));
564 
565   Emit(FADDA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
566 }
567 
568 // SVEFPArithmetic_Predicated.
569 
fabd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)570 void Assembler::fabd(const ZRegister& zd,
571                      const PRegisterM& pg,
572                      const ZRegister& zn,
573                      const ZRegister& zm) {
574   // FABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
575   //  0110 0101 ..00 1000 100. .... .... ....
576   //  size<23:22> | opc<19:16> = 1000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
577 
578   USE(zn);
579   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
580   VIXL_ASSERT(zd.Is(zn));
581   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
582   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
583 
584   Emit(FABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
585 }
586 
fadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)587 void Assembler::fadd(const ZRegister& zd,
588                      const PRegisterM& pg,
589                      const ZRegister& zn,
590                      double imm) {
591   // FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
592   //  0110 0101 ..01 1000 100. ..00 00.. ....
593   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | i1<5> | Zdn<4:0>
594 
595   USE(zn);
596   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
597   VIXL_ASSERT(zd.Is(zn));
598   VIXL_ASSERT(AreSameLaneSize(zd, zn));
599   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
600   VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
601 
602   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
603   Emit(FADD_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
604 }
605 
fadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)606 void Assembler::fadd(const ZRegister& zd,
607                      const PRegisterM& pg,
608                      const ZRegister& zn,
609                      const ZRegister& zm) {
610   // FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
611   //  0110 0101 ..00 0000 100. .... .... ....
612   //  size<23:22> | opc<19:16> = 0000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
613 
614   USE(zn);
615   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
616   VIXL_ASSERT(zd.Is(zn));
617   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
618   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
619 
620   Emit(FADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
621 }
622 
fdiv(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)623 void Assembler::fdiv(const ZRegister& zd,
624                      const PRegisterM& pg,
625                      const ZRegister& zn,
626                      const ZRegister& zm) {
627   // FDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
628   //  0110 0101 ..00 1101 100. .... .... ....
629   //  size<23:22> | opc<19:16> = 1101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
630 
631   USE(zn);
632   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
633   VIXL_ASSERT(zd.Is(zn));
634   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
635   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
636 
637   Emit(FDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
638 }
639 
fdivr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)640 void Assembler::fdivr(const ZRegister& zd,
641                       const PRegisterM& pg,
642                       const ZRegister& zn,
643                       const ZRegister& zm) {
644   // FDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
645   //  0110 0101 ..00 1100 100. .... .... ....
646   //  size<23:22> | opc<19:16> = 1100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
647 
648   USE(zn);
649   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
650   VIXL_ASSERT(zd.Is(zn));
651   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
652   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
653 
654   Emit(FDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
655 }
656 
fmax(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)657 void Assembler::fmax(const ZRegister& zd,
658                      const PRegisterM& pg,
659                      const ZRegister& zn,
660                      double imm) {
661   // FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
662   //  0110 0101 ..01 1110 100. ..00 00.. ....
663   //  size<23:22> | opc<18:16> = 110 | Pg<12:10> | i1<5> | Zdn<4:0>
664 
665   USE(zn);
666   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
667   VIXL_ASSERT(zd.Is(zn));
668   VIXL_ASSERT(AreSameLaneSize(zd, zn));
669   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
670   VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
671 
672   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
673   Emit(FMAX_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
674 }
675 
fmax(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)676 void Assembler::fmax(const ZRegister& zd,
677                      const PRegisterM& pg,
678                      const ZRegister& zn,
679                      const ZRegister& zm) {
680   // FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
681   //  0110 0101 ..00 0110 100. .... .... ....
682   //  size<23:22> | opc<19:16> = 0110 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
683 
684   USE(zn);
685   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
686   VIXL_ASSERT(zd.Is(zn));
687   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
688   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
689 
690   Emit(FMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
691 }
692 
fmaxnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)693 void Assembler::fmaxnm(const ZRegister& zd,
694                        const PRegisterM& pg,
695                        const ZRegister& zn,
696                        double imm) {
697   // FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
698   //  0110 0101 ..01 1100 100. ..00 00.. ....
699   //  size<23:22> | opc<18:16> = 100 | Pg<12:10> | i1<5> | Zdn<4:0>
700 
701   USE(zn);
702   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
703   VIXL_ASSERT(zd.Is(zn));
704   VIXL_ASSERT(AreSameLaneSize(zd, zn));
705   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
706   VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
707 
708   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
709   Emit(FMAXNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
710 }
711 
fmaxnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)712 void Assembler::fmaxnm(const ZRegister& zd,
713                        const PRegisterM& pg,
714                        const ZRegister& zn,
715                        const ZRegister& zm) {
716   // FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
717   //  0110 0101 ..00 0100 100. .... .... ....
718   //  size<23:22> | opc<19:16> = 0100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
719 
720   USE(zn);
721   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
722   VIXL_ASSERT(zd.Is(zn));
723   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
724   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
725 
726   Emit(FMAXNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
727 }
728 
fmin(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)729 void Assembler::fmin(const ZRegister& zd,
730                      const PRegisterM& pg,
731                      const ZRegister& zn,
732                      double imm) {
733   // FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
734   //  0110 0101 ..01 1111 100. ..00 00.. ....
735   //  size<23:22> | opc<18:16> = 111 | Pg<12:10> | i1<5> | Zdn<4:0>
736 
737   USE(zn);
738   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
739   VIXL_ASSERT(zd.Is(zn));
740   VIXL_ASSERT(AreSameLaneSize(zd, zn));
741   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
742   VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
743 
744   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
745   Emit(FMIN_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
746 }
747 
fmin(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)748 void Assembler::fmin(const ZRegister& zd,
749                      const PRegisterM& pg,
750                      const ZRegister& zn,
751                      const ZRegister& zm) {
752   // FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
753   //  0110 0101 ..00 0111 100. .... .... ....
754   //  size<23:22> | opc<19:16> = 0111 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
755 
756   USE(zn);
757   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
758   VIXL_ASSERT(zd.Is(zn));
759   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
760   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
761 
762   Emit(FMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
763 }
764 
fminnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)765 void Assembler::fminnm(const ZRegister& zd,
766                        const PRegisterM& pg,
767                        const ZRegister& zn,
768                        double imm) {
769   // FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
770   //  0110 0101 ..01 1101 100. ..00 00.. ....
771   //  size<23:22> | opc<18:16> = 101 | Pg<12:10> | i1<5> | Zdn<4:0>
772 
773   USE(zn);
774   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
775   VIXL_ASSERT(zd.Is(zn));
776   VIXL_ASSERT(AreSameLaneSize(zd, zn));
777   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
778   VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
779 
780   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
781   Emit(FMINNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
782 }
783 
fminnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)784 void Assembler::fminnm(const ZRegister& zd,
785                        const PRegisterM& pg,
786                        const ZRegister& zn,
787                        const ZRegister& zm) {
788   // FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
789   //  0110 0101 ..00 0101 100. .... .... ....
790   //  size<23:22> | opc<19:16> = 0101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
791 
792   USE(zn);
793   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
794   VIXL_ASSERT(zd.Is(zn));
795   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
796   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
797 
798   Emit(FMINNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
799 }
800 
fmul(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)801 void Assembler::fmul(const ZRegister& zd,
802                      const PRegisterM& pg,
803                      const ZRegister& zn,
804                      double imm) {
805   // FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
806   //  0110 0101 ..01 1010 100. ..00 00.. ....
807   //  size<23:22> | opc<18:16> = 010 | Pg<12:10> | i1<5> | Zdn<4:0>
808 
809   USE(zn);
810   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
811   VIXL_ASSERT(zd.Is(zn));
812   VIXL_ASSERT(AreSameLaneSize(zd, zn));
813   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
814   VIXL_ASSERT((imm == 0.5) || (imm == 2.0));
815 
816   Instr i1 = (imm == 2.0) ? (1 << 5) : 0;
817   Emit(FMUL_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
818 }
819 
fmul(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)820 void Assembler::fmul(const ZRegister& zd,
821                      const PRegisterM& pg,
822                      const ZRegister& zn,
823                      const ZRegister& zm) {
824   // FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
825   //  0110 0101 ..00 0010 100. .... .... ....
826   //  size<23:22> | opc<19:16> = 0010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
827 
828   USE(zn);
829   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
830   VIXL_ASSERT(zd.Is(zn));
831   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
832   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
833 
834   Emit(FMUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
835 }
836 
fmulx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)837 void Assembler::fmulx(const ZRegister& zd,
838                       const PRegisterM& pg,
839                       const ZRegister& zn,
840                       const ZRegister& zm) {
841   // FMULX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
842   //  0110 0101 ..00 1010 100. .... .... ....
843   //  size<23:22> | opc<19:16> = 1010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
844 
845   USE(zn);
846   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
847   VIXL_ASSERT(zd.Is(zn));
848   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
849   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
850 
851   Emit(FMULX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
852 }
853 
fscale(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)854 void Assembler::fscale(const ZRegister& zd,
855                        const PRegisterM& pg,
856                        const ZRegister& zn,
857                        const ZRegister& zm) {
858   // FSCALE <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
859   //  0110 0101 ..00 1001 100. .... .... ....
860   //  size<23:22> | opc<19:16> = 1001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
861 
862   USE(zn);
863   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
864   VIXL_ASSERT(zd.Is(zn));
865   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
866   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
867 
868   Emit(FSCALE_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
869 }
870 
fsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)871 void Assembler::fsub(const ZRegister& zd,
872                      const PRegisterM& pg,
873                      const ZRegister& zn,
874                      double imm) {
875   // FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
876   //  0110 0101 ..01 1001 100. ..00 00.. ....
877   //  size<23:22> | opc<18:16> = 001 | Pg<12:10> | i1<5> | Zdn<4:0>
878 
879   USE(zn);
880   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
881   VIXL_ASSERT(zd.Is(zn));
882   VIXL_ASSERT(AreSameLaneSize(zd, zn));
883   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
884   VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
885 
886   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
887   Emit(FSUB_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
888 }
889 
fsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)890 void Assembler::fsub(const ZRegister& zd,
891                      const PRegisterM& pg,
892                      const ZRegister& zn,
893                      const ZRegister& zm) {
894   // FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
895   //  0110 0101 ..00 0001 100. .... .... ....
896   //  size<23:22> | opc<19:16> = 0001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
897 
898   USE(zn);
899   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
900   VIXL_ASSERT(zd.Is(zn));
901   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
902   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
903 
904   Emit(FSUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
905 }
906 
fsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)907 void Assembler::fsubr(const ZRegister& zd,
908                       const PRegisterM& pg,
909                       const ZRegister& zn,
910                       double imm) {
911   // FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
912   //  0110 0101 ..01 1011 100. ..00 00.. ....
913   //  size<23:22> | opc<18:16> = 011 | Pg<12:10> | i1<5> | Zdn<4:0>
914 
915   USE(zn);
916   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
917   VIXL_ASSERT(zd.Is(zn));
918   VIXL_ASSERT(AreSameLaneSize(zd, zn));
919   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
920   VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
921 
922   Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
923   Emit(FSUBR_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
924 }
925 
fsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)926 void Assembler::fsubr(const ZRegister& zd,
927                       const PRegisterM& pg,
928                       const ZRegister& zn,
929                       const ZRegister& zm) {
930   // FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
931   //  0110 0101 ..00 0011 100. .... .... ....
932   //  size<23:22> | opc<19:16> = 0011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
933 
934   USE(zn);
935   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
936   VIXL_ASSERT(zd.Is(zn));
937   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
938   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
939 
940   Emit(FSUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
941 }
942 
ftmad(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int imm3)943 void Assembler::ftmad(const ZRegister& zd,
944                       const ZRegister& zn,
945                       const ZRegister& zm,
946                       int imm3) {
947   // FTMAD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<imm>
948   //  0110 0101 ..01 0... 1000 00.. .... ....
949   //  size<23:22> | imm3<18:16> | Zm<9:5> | Zdn<4:0>
950 
951   USE(zn);
952   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
953   VIXL_ASSERT(zd.Is(zn));
954   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
955   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
956 
957   Emit(FTMAD_z_zzi | SVESize(zd) | Rd(zd) | Rn(zm) |
958        ImmUnsignedField<18, 16>(imm3));
959 }
960 
961 // SVEFPArithmeticUnpredicated.
962 
fadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)963 void Assembler::fadd(const ZRegister& zd,
964                      const ZRegister& zn,
965                      const ZRegister& zm) {
966   // FADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
967   //  0110 0101 ..0. .... 0000 00.. .... ....
968   //  size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
969 
970   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
971   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
972   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
973 
974   Emit(FADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
975 }
976 
fmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)977 void Assembler::fmul(const ZRegister& zd,
978                      const ZRegister& zn,
979                      const ZRegister& zm) {
980   // FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
981   //  0110 0101 ..0. .... 0000 10.. .... ....
982   //  size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>
983 
984   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
985   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
986   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
987 
988   Emit(FMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
989 }
990 
frecps(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)991 void Assembler::frecps(const ZRegister& zd,
992                        const ZRegister& zn,
993                        const ZRegister& zm) {
994   // FRECPS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
995   //  0110 0101 ..0. .... 0001 10.. .... ....
996   //  size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>
997 
998   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
999   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1000   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1001 
1002   Emit(FRECPS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1003 }
1004 
frsqrts(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)1005 void Assembler::frsqrts(const ZRegister& zd,
1006                         const ZRegister& zn,
1007                         const ZRegister& zm) {
1008   // FRSQRTS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1009   //  0110 0101 ..0. .... 0001 11.. .... ....
1010   //  size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>
1011 
1012   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1013   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1014   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1015 
1016   Emit(FRSQRTS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1017 }
1018 
fsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)1019 void Assembler::fsub(const ZRegister& zd,
1020                      const ZRegister& zn,
1021                      const ZRegister& zm) {
1022   // FSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1023   //  0110 0101 ..0. .... 0000 01.. .... ....
1024   //  size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
1025 
1026   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1027   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1028   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1029 
1030   Emit(FSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1031 }
1032 
ftsmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)1033 void Assembler::ftsmul(const ZRegister& zd,
1034                        const ZRegister& zn,
1035                        const ZRegister& zm) {
1036   // FTSMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1037   //  0110 0101 ..0. .... 0000 11.. .... ....
1038   //  size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>
1039 
1040   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1041   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1042   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1043 
1044   Emit(FTSMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1045 }
1046 
1047 // SVEFPCompareVectors.
1048 
facge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1049 void Assembler::facge(const PRegisterWithLaneSize& pd,
1050                       const PRegisterZ& pg,
1051                       const ZRegister& zn,
1052                       const ZRegister& zm) {
1053   // FACGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1054   //  0110 0101 ..0. .... 110. .... ...1 ....
1055   //  size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1056   //  o3<4> = 1 | Pd<3:0>
1057 
1058   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1059   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1060   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1061 
1062   Emit(FACGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1063 }
1064 
facgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1065 void Assembler::facgt(const PRegisterWithLaneSize& pd,
1066                       const PRegisterZ& pg,
1067                       const ZRegister& zn,
1068                       const ZRegister& zm) {
1069   // FACGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1070   //  0110 0101 ..0. .... 111. .... ...1 ....
1071   //  size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1072   //  o3<4> = 1 | Pd<3:0>
1073 
1074   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1075   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1076   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1077 
1078   Emit(FACGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1079 }
1080 
fcmeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1081 void Assembler::fcmeq(const PRegisterWithLaneSize& pd,
1082                       const PRegisterZ& pg,
1083                       const ZRegister& zn,
1084                       const ZRegister& zm) {
1085   // FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1086   //  0110 0101 ..0. .... 011. .... ...0 ....
1087   //  size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1088   //  o3<4> = 0 | Pd<3:0>
1089 
1090   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1091   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1092   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1093 
1094   Emit(FCMEQ_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1095 }
1096 
fcmge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1097 void Assembler::fcmge(const PRegisterWithLaneSize& pd,
1098                       const PRegisterZ& pg,
1099                       const ZRegister& zn,
1100                       const ZRegister& zm) {
1101   // FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1102   //  0110 0101 ..0. .... 010. .... ...0 ....
1103   //  size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1104   //  o3<4> = 0 | Pd<3:0>
1105 
1106   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1107   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1108   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1109 
1110   Emit(FCMGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1111 }
1112 
fcmgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1113 void Assembler::fcmgt(const PRegisterWithLaneSize& pd,
1114                       const PRegisterZ& pg,
1115                       const ZRegister& zn,
1116                       const ZRegister& zm) {
1117   // FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1118   //  0110 0101 ..0. .... 010. .... ...1 ....
1119   //  size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1120   //  o3<4> = 1 | Pd<3:0>
1121 
1122   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1123   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1124   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1125 
1126   Emit(FCMGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1127 }
1128 
fcmne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1129 void Assembler::fcmne(const PRegisterWithLaneSize& pd,
1130                       const PRegisterZ& pg,
1131                       const ZRegister& zn,
1132                       const ZRegister& zm) {
1133   // FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1134   //  0110 0101 ..0. .... 011. .... ...1 ....
1135   //  size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1136   //  o3<4> = 1 | Pd<3:0>
1137 
1138   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1139   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1140   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1141 
1142   Emit(FCMNE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1143 }
1144 
fcmuo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)1145 void Assembler::fcmuo(const PRegisterWithLaneSize& pd,
1146                       const PRegisterZ& pg,
1147                       const ZRegister& zn,
1148                       const ZRegister& zm) {
1149   // FCMUO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1150   //  0110 0101 ..0. .... 110. .... ...0 ....
1151   //  size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1152   //  o3<4> = 0 | Pd<3:0>
1153 
1154   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1155   VIXL_ASSERT(AreSameLaneSize(zn, zm));
1156   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1157 
1158   Emit(FCMUO_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1159 }
1160 
1161 // SVEFPCompareWithZero.
1162 
fcmeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1163 void Assembler::fcmeq(const PRegisterWithLaneSize& pd,
1164                       const PRegisterZ& pg,
1165                       const ZRegister& zn,
1166                       double zero) {
1167   // FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1168   //  0110 0101 ..01 0010 001. .... ...0 ....
1169   //  size<23:22> | eq<17> = 1 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1170   //  Pd<3:0>
1171 
1172   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1173   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1174   VIXL_ASSERT(zero == 0.0);
1175   USE(zero);
1176 
1177   Emit(FCMEQ_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1178 }
1179 
fcmge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1180 void Assembler::fcmge(const PRegisterWithLaneSize& pd,
1181                       const PRegisterZ& pg,
1182                       const ZRegister& zn,
1183                       double zero) {
1184   // FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1185   //  0110 0101 ..01 0000 001. .... ...0 ....
1186   //  size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1187   //  Pd<3:0>
1188 
1189   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1190   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1191   VIXL_ASSERT(zero == 0.0);
1192   USE(zero);
1193 
1194   Emit(FCMGE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1195 }
1196 
fcmgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1197 void Assembler::fcmgt(const PRegisterWithLaneSize& pd,
1198                       const PRegisterZ& pg,
1199                       const ZRegister& zn,
1200                       double zero) {
1201   // FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1202   //  0110 0101 ..01 0000 001. .... ...1 ....
1203   //  size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
1204   //  Pd<3:0>
1205 
1206   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1207   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1208   VIXL_ASSERT(zero == 0.0);
1209   USE(zero);
1210 
1211   Emit(FCMGT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1212 }
1213 
fcmle(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1214 void Assembler::fcmle(const PRegisterWithLaneSize& pd,
1215                       const PRegisterZ& pg,
1216                       const ZRegister& zn,
1217                       double zero) {
1218   // FCMLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1219   //  0110 0101 ..01 0001 001. .... ...1 ....
1220   //  size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
1221   //  Pd<3:0>
1222 
1223   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1224   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1225   VIXL_ASSERT(zero == 0.0);
1226   USE(zero);
1227 
1228   Emit(FCMLE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1229 }
1230 
fcmlt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1231 void Assembler::fcmlt(const PRegisterWithLaneSize& pd,
1232                       const PRegisterZ& pg,
1233                       const ZRegister& zn,
1234                       double zero) {
1235   // FCMLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1236   //  0110 0101 ..01 0001 001. .... ...0 ....
1237   //  size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1238   //  Pd<3:0>
1239 
1240   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1241   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1242   VIXL_ASSERT(zero == 0.0);
1243   USE(zero);
1244 
1245   Emit(FCMLT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1246 }
1247 
fcmne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)1248 void Assembler::fcmne(const PRegisterWithLaneSize& pd,
1249                       const PRegisterZ& pg,
1250                       const ZRegister& zn,
1251                       double zero) {
1252   // FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1253   //  0110 0101 ..01 0011 001. .... ...0 ....
1254   //  size<23:22> | eq<17> = 1 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1255   //  Pd<3:0>
1256 
1257   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1258   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1259   VIXL_ASSERT(zero == 0.0);
1260   USE(zero);
1261 
1262   Emit(FCMNE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1263 }
1264 
1265 // SVEFPComplexAddition.
1266 
fcadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm,int rot)1267 void Assembler::fcadd(const ZRegister& zd,
1268                       const PRegisterM& pg,
1269                       const ZRegister& zn,
1270                       const ZRegister& zm,
1271                       int rot) {
1272   // FCADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>, <const>
1273   //  0110 0100 ..00 000. 100. .... .... ....
1274   //  size<23:22> | rot<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1275 
1276   USE(zn);
1277   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1278   VIXL_ASSERT(zd.Is(zn));
1279   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1280   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1281   VIXL_ASSERT((rot == 90) || (rot == 270));
1282 
1283   Instr rotate_bit = (rot == 90) ? 0 : (1 << 16);
1284   Emit(FCADD_z_p_zz | rotate_bit | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
1285 }
1286 
1287 // SVEFPComplexMulAdd.
1288 
fcmla(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm,int rot)1289 void Assembler::fcmla(const ZRegister& zda,
1290                       const PRegisterM& pg,
1291                       const ZRegister& zn,
1292                       const ZRegister& zm,
1293                       int rot) {
1294   // FCMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>, <const>
1295   //  0110 0100 ..0. .... 0... .... .... ....
1296   //  size<23:22> | Zm<20:16> | rot<14:13> | Pg<12:10> | Zn<9:5> | Zda<4:0>
1297 
1298   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1299   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1300   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1301   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
1302 
1303   Instr rotate_bit = (rot / 90) << 13;
1304   Emit(FCMLA_z_p_zzz | rotate_bit | SVESize(zda) | Rd(zda) | PgLow8(pg) |
1305        Rn(zn) | Rm(zm));
1306 }
1307 
1308 // SVEFPComplexMulAddIndex.
1309 
fcmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index,int rot)1310 void Assembler::fcmla(const ZRegister& zda,
1311                       const ZRegister& zn,
1312                       const ZRegister& zm,
1313                       int index,
1314                       int rot) {
1315   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1316   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1317   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
1318 
1319   Instr rotate_bit = (rot / 90) << 10;
1320   Emit(FCMLA_z_zzzi_h | SVEMulComplexIndexHelper(zm, index) | rotate_bit |
1321        Rd(zda) | Rn(zn));
1322 }
1323 
1324 // SVEFPFastReduction.
1325 
faddv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)1326 void Assembler::faddv(const VRegister& vd,
1327                       const PRegister& pg,
1328                       const ZRegister& zn) {
1329   // FADDV <V><d>, <Pg>, <Zn>.<T>
1330   //  0110 0101 ..00 0000 001. .... .... ....
1331   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1332 
1333   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1334   VIXL_ASSERT(vd.IsScalar());
1335   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1336   VIXL_ASSERT(AreSameLaneSize(zn, vd));
1337 
1338   Emit(FADDV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1339 }
1340 
fmaxnmv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)1341 void Assembler::fmaxnmv(const VRegister& vd,
1342                         const PRegister& pg,
1343                         const ZRegister& zn) {
1344   // FMAXNMV <V><d>, <Pg>, <Zn>.<T>
1345   //  0110 0101 ..00 0100 001. .... .... ....
1346   //  size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1347 
1348   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1349   VIXL_ASSERT(vd.IsScalar());
1350   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1351   VIXL_ASSERT(AreSameLaneSize(zn, vd));
1352 
1353   Emit(FMAXNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1354 }
1355 
fmaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)1356 void Assembler::fmaxv(const VRegister& vd,
1357                       const PRegister& pg,
1358                       const ZRegister& zn) {
1359   // FMAXV <V><d>, <Pg>, <Zn>.<T>
1360   //  0110 0101 ..00 0110 001. .... .... ....
1361   //  size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1362 
1363   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1364   VIXL_ASSERT(vd.IsScalar());
1365   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1366   VIXL_ASSERT(AreSameLaneSize(zn, vd));
1367 
1368   Emit(FMAXV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1369 }
1370 
fminnmv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)1371 void Assembler::fminnmv(const VRegister& vd,
1372                         const PRegister& pg,
1373                         const ZRegister& zn) {
1374   // FMINNMV <V><d>, <Pg>, <Zn>.<T>
1375   //  0110 0101 ..00 0101 001. .... .... ....
1376   //  size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1377 
1378   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1379   VIXL_ASSERT(vd.IsScalar());
1380   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1381   VIXL_ASSERT(AreSameLaneSize(zn, vd));
1382 
1383   Emit(FMINNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1384 }
1385 
fminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)1386 void Assembler::fminv(const VRegister& vd,
1387                       const PRegister& pg,
1388                       const ZRegister& zn) {
1389   // FMINV <V><d>, <Pg>, <Zn>.<T>
1390   //  0110 0101 ..00 0111 001. .... .... ....
1391   //  size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1392 
1393   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1394   VIXL_ASSERT(vd.IsScalar());
1395   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1396   VIXL_ASSERT(AreSameLaneSize(zn, vd));
1397 
1398   Emit(FMINV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1399 }
1400 
1401 // SVEFPMulAdd.
1402 
fmad(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)1403 void Assembler::fmad(const ZRegister& zdn,
1404                      const PRegisterM& pg,
1405                      const ZRegister& zm,
1406                      const ZRegister& za) {
1407   // FMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1408   //  0110 0101 ..1. .... 100. .... .... ....
1409   //  size<23:22> | Za<20:16> | opc<14:13> = 00 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1410 
1411   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1412   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1413   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1414 
1415   Emit(FMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1416 }
1417 
fmla(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)1418 void Assembler::fmla(const ZRegister& zda,
1419                      const PRegisterM& pg,
1420                      const ZRegister& zn,
1421                      const ZRegister& zm) {
1422   // FMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1423   //  0110 0101 ..1. .... 000. .... .... ....
1424   //  size<23:22> | Zm<20:16> | opc<14:13> = 00 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1425 
1426   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1427   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1428   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1429 
1430   Emit(FMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1431 }
1432 
fmls(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)1433 void Assembler::fmls(const ZRegister& zda,
1434                      const PRegisterM& pg,
1435                      const ZRegister& zn,
1436                      const ZRegister& zm) {
1437   // FMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1438   //  0110 0101 ..1. .... 001. .... .... ....
1439   //  size<23:22> | Zm<20:16> | opc<14:13> = 01 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1440 
1441   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1442   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1443   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1444 
1445   Emit(FMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1446 }
1447 
fmsb(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)1448 void Assembler::fmsb(const ZRegister& zdn,
1449                      const PRegisterM& pg,
1450                      const ZRegister& zm,
1451                      const ZRegister& za) {
1452   // FMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1453   //  0110 0101 ..1. .... 101. .... .... ....
1454   //  size<23:22> | Za<20:16> | opc<14:13> = 01 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1455 
1456   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1457   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1458   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1459 
1460   Emit(FMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1461 }
1462 
fnmad(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)1463 void Assembler::fnmad(const ZRegister& zdn,
1464                       const PRegisterM& pg,
1465                       const ZRegister& zm,
1466                       const ZRegister& za) {
1467   // FNMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1468   //  0110 0101 ..1. .... 110. .... .... ....
1469   //  size<23:22> | Za<20:16> | opc<14:13> = 10 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1470 
1471   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1472   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1473   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1474 
1475   Emit(FNMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1476 }
1477 
fnmla(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)1478 void Assembler::fnmla(const ZRegister& zda,
1479                       const PRegisterM& pg,
1480                       const ZRegister& zn,
1481                       const ZRegister& zm) {
1482   // FNMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1483   //  0110 0101 ..1. .... 010. .... .... ....
1484   //  size<23:22> | Zm<20:16> | opc<14:13> = 10 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1485 
1486   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1487   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1488   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1489 
1490   Emit(FNMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1491 }
1492 
fnmls(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)1493 void Assembler::fnmls(const ZRegister& zda,
1494                       const PRegisterM& pg,
1495                       const ZRegister& zn,
1496                       const ZRegister& zm) {
1497   // FNMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1498   //  0110 0101 ..1. .... 011. .... .... ....
1499   //  size<23:22> | Zm<20:16> | opc<14:13> = 11 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1500 
1501   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1502   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1503   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1504 
1505   Emit(FNMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1506 }
1507 
fnmsb(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)1508 void Assembler::fnmsb(const ZRegister& zdn,
1509                       const PRegisterM& pg,
1510                       const ZRegister& zm,
1511                       const ZRegister& za) {
1512   // FNMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1513   //  0110 0101 ..1. .... 111. .... .... ....
1514   //  size<23:22> | Za<20:16> | opc<14:13> = 11 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1515 
1516   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1517   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1518   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1519 
1520   Emit(FNMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1521 }
1522 
SVEMulIndexHelper(unsigned lane_size_in_bytes_log2,const ZRegister & zm,int index,Instr op_h,Instr op_s,Instr op_d)1523 Instr Assembler::SVEMulIndexHelper(unsigned lane_size_in_bytes_log2,
1524                                    const ZRegister& zm,
1525                                    int index,
1526                                    Instr op_h,
1527                                    Instr op_s,
1528                                    Instr op_d) {
1529   Instr size = lane_size_in_bytes_log2 << SVESize_offset;
1530   Instr zm_with_index = Rm(zm);
1531   Instr op = 0xffffffff;
1532   // Allowable register number and lane index depends on the lane size.
1533   switch (lane_size_in_bytes_log2) {
1534     case kHRegSizeInBytesLog2:
1535       VIXL_ASSERT(zm.GetCode() <= 7);
1536       VIXL_ASSERT(IsUint3(index));
1537       // For H-sized lanes, size is encoded as 0b0x, where x is used as the top
1538       // bit of the index. So, if index is less than four, the top bit of index
1539       // is zero, and therefore size is 0b00. Otherwise, it's 0b01, the usual
1540       // encoding for H-sized lanes.
1541       if (index < 4) size = 0;
1542       // Top two bits of "zm" encode the index.
1543       zm_with_index |= (index & 3) << (Rm_offset + 3);
1544       op = op_h;
1545       break;
1546     case kSRegSizeInBytesLog2:
1547       VIXL_CHECK(zm.GetCode() <= 7);
1548       VIXL_CHECK(IsUint2(index));
1549       // Top two bits of "zm" encode the index.
1550       zm_with_index |= (index & 3) << (Rm_offset + 3);
1551       op = op_s;
1552       break;
1553     case kDRegSizeInBytesLog2:
1554       VIXL_CHECK(zm.GetCode() <= 15);
1555       VIXL_CHECK(IsUint1(index));
1556       // Top bit of "zm" encodes the index.
1557       zm_with_index |= (index & 1) << (Rm_offset + 4);
1558       op = op_d;
1559       break;
1560     default:
1561       VIXL_UNIMPLEMENTED();
1562   }
1563   return op | zm_with_index | size;
1564 }
1565 
SVEMulLongIndexHelper(const ZRegister & zm,int index)1566 Instr Assembler::SVEMulLongIndexHelper(const ZRegister& zm, int index) {
1567   Instr imm_field;
1568   Instr zm_id;
1569   if (zm.IsLaneSizeH()) {
1570     VIXL_CHECK(zm.GetCode() <= 7);
1571     VIXL_CHECK(IsUint3(index));
1572     imm_field = ExtractUnsignedBitfield32(2, 1, index) << 19;
1573     zm_id = Rx<18, 16>(zm);
1574   } else {
1575     VIXL_ASSERT(zm.IsLaneSizeS());
1576     VIXL_CHECK(zm.GetCode() <= 15);
1577     VIXL_CHECK(IsUint2(index));
1578     imm_field = ExtractBit(index, 1) << 20;
1579     zm_id = Rx<19, 16>(zm);
1580   }
1581 
1582   // Synthesize the low part of immediate encoding.
1583   imm_field |= ExtractBit(index, 0) << 11;
1584 
1585   return zm_id | imm_field;
1586 }
1587 
SVEMulComplexIndexHelper(const ZRegister & zm,int index)1588 Instr Assembler::SVEMulComplexIndexHelper(const ZRegister& zm, int index) {
1589   Instr zm_idx_size;
1590   if (zm.IsLaneSizeH()) {
1591     // Zm<18:16> | i2<20:19>
1592     VIXL_CHECK(zm.GetCode() <= 7);
1593     VIXL_CHECK(IsUint2(index));
1594     zm_idx_size = (index << 19) | Rx<18, 16>(zm) | 0;
1595   } else {
1596     VIXL_ASSERT(zm.IsLaneSizeS());
1597     // Zm<19:16> | i1<20>
1598     VIXL_CHECK(zm.GetCode() <= 15);
1599     VIXL_CHECK(IsUint1(index));
1600     zm_idx_size = (index << 20) | Rx<19, 16>(zm) | (1 << 22);
1601   }
1602   return zm_idx_size;
1603 }
1604 
1605 // SVEFPMulAddIndex.
1606 
fmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)1607 void Assembler::fmla(const ZRegister& zda,
1608                      const ZRegister& zn,
1609                      const ZRegister& zm,
1610                      int index) {
1611   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1612   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1613 
1614   // The encoding of opcode, index, Zm, and size are synthesized in this
1615   // variable.
1616   Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
1617                                            zm,
1618                                            index,
1619                                            FMLA_z_zzzi_h,
1620                                            FMLA_z_zzzi_s,
1621                                            FMLA_z_zzzi_d);
1622 
1623   Emit(synthesized_op | Rd(zda) | Rn(zn));
1624 }
1625 
fmls(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)1626 void Assembler::fmls(const ZRegister& zda,
1627                      const ZRegister& zn,
1628                      const ZRegister& zm,
1629                      int index) {
1630   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1631   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1632 
1633   // The encoding of opcode, index, Zm, and size are synthesized in this
1634   // variable.
1635   Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
1636                                            zm,
1637                                            index,
1638                                            FMLS_z_zzzi_h,
1639                                            FMLS_z_zzzi_s,
1640                                            FMLS_z_zzzi_d);
1641 
1642   Emit(synthesized_op | Rd(zda) | Rn(zn));
1643 }
1644 
1645 // SVEFPMulIndex.
1646 
1647 // This prototype maps to 3 instruction encodings:
fmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,unsigned index)1648 void Assembler::fmul(const ZRegister& zd,
1649                      const ZRegister& zn,
1650                      const ZRegister& zm,
1651                      unsigned index) {
1652   // FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>[<imm>]
1653   //  0110 0100 ..1. .... 0010 00.. .... ....
1654   //  size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>
1655 
1656   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1657   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1658 
1659   // The encoding of opcode, index, Zm, and size are synthesized in this
1660   // variable.
1661   Instr synthesized_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
1662                                            zm,
1663                                            index,
1664                                            FMUL_z_zzi_h,
1665                                            FMUL_z_zzi_s,
1666                                            FMUL_z_zzi_d);
1667 
1668   Emit(synthesized_op | Rd(zd) | Rn(zn));
1669 }
1670 
1671 // SVEFPUnaryOpPredicated.
1672 
fcvt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1673 void Assembler::fcvt(const ZRegister& zd,
1674                      const PRegisterM& pg,
1675                      const ZRegister& zn) {
1676   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1677 
1678   Instr op = 0xffffffff;
1679   switch (zn.GetLaneSizeInBytes()) {
1680     case kHRegSizeInBytes:
1681       switch (zd.GetLaneSizeInBytes()) {
1682         case kSRegSizeInBytes:
1683           op = FCVT_z_p_z_h2s;
1684           break;
1685         case kDRegSizeInBytes:
1686           op = FCVT_z_p_z_h2d;
1687           break;
1688       }
1689       break;
1690     case kSRegSizeInBytes:
1691       switch (zd.GetLaneSizeInBytes()) {
1692         case kHRegSizeInBytes:
1693           op = FCVT_z_p_z_s2h;
1694           break;
1695         case kDRegSizeInBytes:
1696           op = FCVT_z_p_z_s2d;
1697           break;
1698       }
1699       break;
1700     case kDRegSizeInBytes:
1701       switch (zd.GetLaneSizeInBytes()) {
1702         case kHRegSizeInBytes:
1703           op = FCVT_z_p_z_d2h;
1704           break;
1705         case kSRegSizeInBytes:
1706           op = FCVT_z_p_z_d2s;
1707           break;
1708       }
1709       break;
1710   }
1711   VIXL_ASSERT(op != 0xffffffff);
1712 
1713   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1714 }
1715 
fcvtzs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1716 void Assembler::fcvtzs(const ZRegister& zd,
1717                        const PRegisterM& pg,
1718                        const ZRegister& zn) {
1719   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1720   Instr op = 0xffffffff;
1721   switch (zn.GetLaneSizeInBytes()) {
1722     case kHRegSizeInBytes:
1723       switch (zd.GetLaneSizeInBytes()) {
1724         case kHRegSizeInBytes:
1725           op = FCVTZS_z_p_z_fp162h;
1726           break;
1727         case kSRegSizeInBytes:
1728           op = FCVTZS_z_p_z_fp162w;
1729           break;
1730         case kDRegSizeInBytes:
1731           op = FCVTZS_z_p_z_fp162x;
1732           break;
1733       }
1734       break;
1735     case kSRegSizeInBytes:
1736       switch (zd.GetLaneSizeInBytes()) {
1737         case kSRegSizeInBytes:
1738           op = FCVTZS_z_p_z_s2w;
1739           break;
1740         case kDRegSizeInBytes:
1741           op = FCVTZS_z_p_z_s2x;
1742           break;
1743       }
1744       break;
1745     case kDRegSizeInBytes:
1746       switch (zd.GetLaneSizeInBytes()) {
1747         case kSRegSizeInBytes:
1748           op = FCVTZS_z_p_z_d2w;
1749           break;
1750         case kDRegSizeInBytes:
1751           op = FCVTZS_z_p_z_d2x;
1752           break;
1753       }
1754       break;
1755   }
1756   VIXL_ASSERT(op != 0xffffffff);
1757 
1758   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1759 }
1760 
fcvtzu(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1761 void Assembler::fcvtzu(const ZRegister& zd,
1762                        const PRegisterM& pg,
1763                        const ZRegister& zn) {
1764   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1765   Instr op = 0xffffffff;
1766   switch (zn.GetLaneSizeInBytes()) {
1767     case kHRegSizeInBytes:
1768       switch (zd.GetLaneSizeInBytes()) {
1769         case kHRegSizeInBytes:
1770           op = FCVTZU_z_p_z_fp162h;
1771           break;
1772         case kSRegSizeInBytes:
1773           op = FCVTZU_z_p_z_fp162w;
1774           break;
1775         case kDRegSizeInBytes:
1776           op = FCVTZU_z_p_z_fp162x;
1777           break;
1778       }
1779       break;
1780     case kSRegSizeInBytes:
1781       switch (zd.GetLaneSizeInBytes()) {
1782         case kSRegSizeInBytes:
1783           op = FCVTZU_z_p_z_s2w;
1784           break;
1785         case kDRegSizeInBytes:
1786           op = FCVTZU_z_p_z_s2x;
1787           break;
1788       }
1789       break;
1790     case kDRegSizeInBytes:
1791       switch (zd.GetLaneSizeInBytes()) {
1792         case kSRegSizeInBytes:
1793           op = FCVTZU_z_p_z_d2w;
1794           break;
1795         case kDRegSizeInBytes:
1796           op = FCVTZU_z_p_z_d2x;
1797           break;
1798       }
1799       break;
1800   }
1801   VIXL_ASSERT(op != 0xffffffff);
1802 
1803   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1804 }
1805 
frecpx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1806 void Assembler::frecpx(const ZRegister& zd,
1807                        const PRegisterM& pg,
1808                        const ZRegister& zn) {
1809   // FRECPX <Zd>.<T>, <Pg>/M, <Zn>.<T>
1810   //  0110 0101 ..00 1100 101. .... .... ....
1811   //  size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>
1812 
1813   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1814   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1815   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1816 
1817   Emit(FRECPX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1818 }
1819 
frinta(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1820 void Assembler::frinta(const ZRegister& zd,
1821                        const PRegisterM& pg,
1822                        const ZRegister& zn) {
1823   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1824   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1825   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1826 
1827   Emit(FRINTA_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1828 }
1829 
frinti(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1830 void Assembler::frinti(const ZRegister& zd,
1831                        const PRegisterM& pg,
1832                        const ZRegister& zn) {
1833   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1834   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1835   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1836 
1837   Emit(FRINTI_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1838 }
1839 
frintm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1840 void Assembler::frintm(const ZRegister& zd,
1841                        const PRegisterM& pg,
1842                        const ZRegister& zn) {
1843   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1844   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1845   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1846 
1847   Emit(FRINTM_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1848 }
1849 
frintn(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1850 void Assembler::frintn(const ZRegister& zd,
1851                        const PRegisterM& pg,
1852                        const ZRegister& zn) {
1853   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1854   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1855   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1856 
1857   Emit(FRINTN_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1858 }
1859 
frintp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1860 void Assembler::frintp(const ZRegister& zd,
1861                        const PRegisterM& pg,
1862                        const ZRegister& zn) {
1863   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1864   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1865   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1866 
1867   Emit(FRINTP_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1868 }
1869 
frintx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1870 void Assembler::frintx(const ZRegister& zd,
1871                        const PRegisterM& pg,
1872                        const ZRegister& zn) {
1873   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1874   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1875   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1876 
1877   Emit(FRINTX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1878 }
1879 
frintz(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1880 void Assembler::frintz(const ZRegister& zd,
1881                        const PRegisterM& pg,
1882                        const ZRegister& zn) {
1883   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1884   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1885   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1886 
1887   Emit(FRINTZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1888 }
1889 
fsqrt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1890 void Assembler::fsqrt(const ZRegister& zd,
1891                       const PRegisterM& pg,
1892                       const ZRegister& zn) {
1893   // FSQRT <Zd>.<T>, <Pg>/M, <Zn>.<T>
1894   //  0110 0101 ..00 1101 101. .... .... ....
1895   //  size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>
1896 
1897   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1898   VIXL_ASSERT(AreSameLaneSize(zd, zn));
1899   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1900 
1901   Emit(FSQRT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1902 }
1903 
scvtf(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1904 void Assembler::scvtf(const ZRegister& zd,
1905                       const PRegisterM& pg,
1906                       const ZRegister& zn) {
1907   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1908   Instr op = 0xffffffff;
1909   switch (zn.GetLaneSizeInBytes()) {
1910     case kHRegSizeInBytes:
1911       switch (zd.GetLaneSizeInBytes()) {
1912         case kHRegSizeInBytes:
1913           op = SCVTF_z_p_z_h2fp16;
1914           break;
1915       }
1916       break;
1917     case kSRegSizeInBytes:
1918       switch (zd.GetLaneSizeInBytes()) {
1919         case kHRegSizeInBytes:
1920           op = SCVTF_z_p_z_w2fp16;
1921           break;
1922         case kSRegSizeInBytes:
1923           op = SCVTF_z_p_z_w2s;
1924           break;
1925         case kDRegSizeInBytes:
1926           op = SCVTF_z_p_z_w2d;
1927           break;
1928       }
1929       break;
1930     case kDRegSizeInBytes:
1931       switch (zd.GetLaneSizeInBytes()) {
1932         case kHRegSizeInBytes:
1933           op = SCVTF_z_p_z_x2fp16;
1934           break;
1935         case kSRegSizeInBytes:
1936           op = SCVTF_z_p_z_x2s;
1937           break;
1938         case kDRegSizeInBytes:
1939           op = SCVTF_z_p_z_x2d;
1940           break;
1941       }
1942       break;
1943   }
1944   VIXL_ASSERT(op != 0xffffffff);
1945 
1946   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1947 }
1948 
ucvtf(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)1949 void Assembler::ucvtf(const ZRegister& zd,
1950                       const PRegisterM& pg,
1951                       const ZRegister& zn) {
1952   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1953   Instr op = 0xffffffff;
1954   switch (zn.GetLaneSizeInBytes()) {
1955     case kHRegSizeInBytes:
1956       switch (zd.GetLaneSizeInBytes()) {
1957         case kHRegSizeInBytes:
1958           op = UCVTF_z_p_z_h2fp16;
1959           break;
1960       }
1961       break;
1962     case kSRegSizeInBytes:
1963       switch (zd.GetLaneSizeInBytes()) {
1964         case kHRegSizeInBytes:
1965           op = UCVTF_z_p_z_w2fp16;
1966           break;
1967         case kSRegSizeInBytes:
1968           op = UCVTF_z_p_z_w2s;
1969           break;
1970         case kDRegSizeInBytes:
1971           op = UCVTF_z_p_z_w2d;
1972           break;
1973       }
1974       break;
1975     case kDRegSizeInBytes:
1976       switch (zd.GetLaneSizeInBytes()) {
1977         case kHRegSizeInBytes:
1978           op = UCVTF_z_p_z_x2fp16;
1979           break;
1980         case kSRegSizeInBytes:
1981           op = UCVTF_z_p_z_x2s;
1982           break;
1983         case kDRegSizeInBytes:
1984           op = UCVTF_z_p_z_x2d;
1985           break;
1986       }
1987       break;
1988   }
1989   VIXL_ASSERT(op != 0xffffffff);
1990 
1991   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1992 }
1993 
1994 // SVEFPUnaryOpUnpredicated.
1995 
frecpe(const ZRegister & zd,const ZRegister & zn)1996 void Assembler::frecpe(const ZRegister& zd, const ZRegister& zn) {
1997   // FRECPE <Zd>.<T>, <Zn>.<T>
1998   //  0110 0101 ..00 1110 0011 00.. .... ....
1999   //  size<23:22> | opc<18:16> = 110 | Zn<9:5> | Zd<4:0>
2000 
2001   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2002   VIXL_ASSERT(AreSameLaneSize(zd, zn));
2003   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
2004 
2005   Emit(FRECPE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
2006 }
2007 
frsqrte(const ZRegister & zd,const ZRegister & zn)2008 void Assembler::frsqrte(const ZRegister& zd, const ZRegister& zn) {
2009   // FRSQRTE <Zd>.<T>, <Zn>.<T>
2010   //  0110 0101 ..00 1111 0011 00.. .... ....
2011   //  size<23:22> | opc<18:16> = 111 | Zn<9:5> | Zd<4:0>
2012 
2013   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2014   VIXL_ASSERT(AreSameLaneSize(zd, zn));
2015   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
2016 
2017   Emit(FRSQRTE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
2018 }
2019 
2020 // SVEIncDecByPredicateCount.
2021 
decp(const Register & rdn,const PRegisterWithLaneSize & pg)2022 void Assembler::decp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2023   // DECP <Xdn>, <Pg>.<T>
2024   //  0010 0101 ..10 1101 1000 100. .... ....
2025   //  size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |
2026   //  Rdn<4:0>
2027 
2028   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2029   VIXL_ASSERT(rdn.IsX());
2030 
2031   Emit(DECP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2032 }
2033 
decp(const ZRegister & zdn,const PRegister & pg)2034 void Assembler::decp(const ZRegister& zdn, const PRegister& pg) {
2035   // DECP <Zdn>.<T>, <Pg>
2036   //  0010 0101 ..10 1101 1000 000. .... ....
2037   //  size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |
2038   //  Zdn<4:0>
2039 
2040   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2041   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2042   VIXL_ASSERT(pg.IsUnqualified());
2043 
2044   Emit(DECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2045 }
2046 
incp(const Register & rdn,const PRegisterWithLaneSize & pg)2047 void Assembler::incp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2048   // INCP <Xdn>, <Pg>.<T>
2049   //  0010 0101 ..10 1100 1000 100. .... ....
2050   //  size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |
2051   //  Rdn<4:0>
2052 
2053   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2054   VIXL_ASSERT(rdn.IsX());
2055 
2056   Emit(INCP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2057 }
2058 
incp(const ZRegister & zdn,const PRegister & pg)2059 void Assembler::incp(const ZRegister& zdn, const PRegister& pg) {
2060   // INCP <Zdn>.<T>, <Pg>
2061   //  0010 0101 ..10 1100 1000 000. .... ....
2062   //  size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |
2063   //  Zdn<4:0>
2064 
2065   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2066   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2067   VIXL_ASSERT(pg.IsUnqualified());
2068 
2069   Emit(INCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2070 }
2071 
sqdecp(const Register & xd,const PRegisterWithLaneSize & pg,const Register & wn)2072 void Assembler::sqdecp(const Register& xd,
2073                        const PRegisterWithLaneSize& pg,
2074                        const Register& wn) {
2075   // SQDECP <Xdn>, <Pg>.<T>, <Wdn>
2076   //  0010 0101 ..10 1010 1000 100. .... ....
2077   //  size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2078   //  Rdn<4:0>
2079 
2080   USE(wn);
2081   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2082   VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));
2083 
2084   Emit(SQDECP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));
2085 }
2086 
sqdecp(const Register & xdn,const PRegisterWithLaneSize & pg)2087 void Assembler::sqdecp(const Register& xdn, const PRegisterWithLaneSize& pg) {
2088   // SQDECP <Xdn>, <Pg>.<T>
2089   //  0010 0101 ..10 1010 1000 110. .... ....
2090   //  size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |
2091   //  Rdn<4:0>
2092 
2093   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2094   VIXL_ASSERT(xdn.IsX());
2095 
2096   Emit(SQDECP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));
2097 }
2098 
sqdecp(const ZRegister & zdn,const PRegister & pg)2099 void Assembler::sqdecp(const ZRegister& zdn, const PRegister& pg) {
2100   // SQDECP <Zdn>.<T>, <Pg>
2101   //  0010 0101 ..10 1010 1000 000. .... ....
2102   //  size<23:22> | D<17> = 1 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2103 
2104   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2105   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2106   VIXL_ASSERT(pg.IsUnqualified());
2107 
2108   Emit(SQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2109 }
2110 
sqincp(const Register & xd,const PRegisterWithLaneSize & pg,const Register & wn)2111 void Assembler::sqincp(const Register& xd,
2112                        const PRegisterWithLaneSize& pg,
2113                        const Register& wn) {
2114   // SQINCP <Xdn>, <Pg>.<T>, <Wdn>
2115   //  0010 0101 ..10 1000 1000 100. .... ....
2116   //  size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2117   //  Rdn<4:0>
2118 
2119   USE(wn);
2120   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2121   VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));
2122 
2123   Emit(SQINCP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));
2124 }
2125 
sqincp(const Register & xdn,const PRegisterWithLaneSize & pg)2126 void Assembler::sqincp(const Register& xdn, const PRegisterWithLaneSize& pg) {
2127   // SQINCP <Xdn>, <Pg>.<T>
2128   //  0010 0101 ..10 1000 1000 110. .... ....
2129   //  size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |
2130   //  Rdn<4:0>
2131 
2132   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2133   VIXL_ASSERT(xdn.IsX());
2134 
2135   Emit(SQINCP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));
2136 }
2137 
sqincp(const ZRegister & zdn,const PRegister & pg)2138 void Assembler::sqincp(const ZRegister& zdn, const PRegister& pg) {
2139   // SQINCP <Zdn>.<T>, <Pg>
2140   //  0010 0101 ..10 1000 1000 000. .... ....
2141   //  size<23:22> | D<17> = 0 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2142 
2143   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2144   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2145   VIXL_ASSERT(pg.IsUnqualified());
2146 
2147   Emit(SQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2148 }
2149 
uqdecp(const Register & rdn,const PRegisterWithLaneSize & pg)2150 void Assembler::uqdecp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2151   // UQDECP <Wdn>, <Pg>.<T>
2152   // UQDECP <Xdn>, <Pg>.<T>
2153   //  0010 0101 ..10 1011 1000 10.. .... ....
2154   //  size<23:22> | D<17> = 1 | U<16> = 1 | sf<10> | op<9> = 0 | Pg<8:5> |
2155   //  Rdn<4:0>
2156 
2157   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2158 
2159   Instr op = rdn.IsX() ? UQDECP_r_p_r_x : UQDECP_r_p_r_uw;
2160   Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2161 }
2162 
uqdecp(const ZRegister & zdn,const PRegister & pg)2163 void Assembler::uqdecp(const ZRegister& zdn, const PRegister& pg) {
2164   // UQDECP <Zdn>.<T>, <Pg>
2165   //  0010 0101 ..10 1011 1000 000. .... ....
2166   //  size<23:22> | D<17> = 1 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2167 
2168   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2169   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2170   VIXL_ASSERT(pg.IsUnqualified());
2171 
2172   Emit(UQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2173 }
2174 
uqincp(const Register & rdn,const PRegisterWithLaneSize & pg)2175 void Assembler::uqincp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2176   // UQINCP <Wdn>, <Pg>.<T>
2177   //  0010 0101 ..10 1001 1000 100. .... ....
2178   //  size<23:22> | D<17> = 0 | U<16> = 1 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2179   //  Rdn<4:0>
2180 
2181   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2182 
2183   Instr op = rdn.IsX() ? UQINCP_r_p_r_x : UQINCP_r_p_r_uw;
2184   Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2185 }
2186 
uqincp(const ZRegister & zdn,const PRegister & pg)2187 void Assembler::uqincp(const ZRegister& zdn, const PRegister& pg) {
2188   // UQINCP <Zdn>.<T>, <Pg>
2189   //  0010 0101 ..10 1001 1000 000. .... ....
2190   //  size<23:22> | D<17> = 0 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2191 
2192   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2193   VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2194   VIXL_ASSERT(pg.IsUnqualified());
2195 
2196   Emit(UQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2197 }
2198 
2199 // SVEIndexGeneration.
2200 
index(const ZRegister & zd,int start,int step)2201 void Assembler::index(const ZRegister& zd, int start, int step) {
2202   // INDEX <Zd>.<T>, #<imm1>, #<imm2>
2203   //  0000 0100 ..1. .... 0100 00.. .... ....
2204   //  size<23:22> | step<20:16> | start<9:5> | Zd<4:0>
2205 
2206   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2207 
2208   Emit(INDEX_z_ii | SVESize(zd) | ImmField<20, 16>(step) |
2209        ImmField<9, 5>(start) | Rd(zd));
2210 }
2211 
index(const ZRegister & zd,const Register & rn,const Register & rm)2212 void Assembler::index(const ZRegister& zd,
2213                       const Register& rn,
2214                       const Register& rm) {
2215   // INDEX <Zd>.<T>, <R><n>, <R><m>
2216   //  0000 0100 ..1. .... 0100 11.. .... ....
2217   //  size<23:22> | Rm<20:16> | Rn<9:5> | Zd<4:0>
2218 
2219   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2220   VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
2221               zd.GetLaneSizeInBits());
2222   VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=
2223               zd.GetLaneSizeInBits());
2224 
2225   Emit(INDEX_z_rr | SVESize(zd) | Rd(zd) | Rn(rn) | Rm(rm));
2226 }
2227 
index(const ZRegister & zd,const Register & rn,int imm5)2228 void Assembler::index(const ZRegister& zd, const Register& rn, int imm5) {
2229   // INDEX <Zd>.<T>, <R><n>, #<imm>
2230   //  0000 0100 ..1. .... 0100 01.. .... ....
2231   //  size<23:22> | imm5<20:16> | Rn<9:5> | Zd<4:0>
2232 
2233   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2234   VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
2235               zd.GetLaneSizeInBits());
2236 
2237   Emit(INDEX_z_ri | SVESize(zd) | Rd(zd) | Rn(rn) | ImmField<20, 16>(imm5));
2238 }
2239 
index(const ZRegister & zd,int imm5,const Register & rm)2240 void Assembler::index(const ZRegister& zd, int imm5, const Register& rm) {
2241   // INDEX <Zd>.<T>, #<imm>, <R><m>
2242   //  0000 0100 ..1. .... 0100 10.. .... ....
2243   //  size<23:22> | Rm<20:16> | imm5<9:5> | Zd<4:0>
2244 
2245   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2246   VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=
2247               zd.GetLaneSizeInBits());
2248 
2249   Emit(INDEX_z_ir | SVESize(zd) | Rd(zd) | ImmField<9, 5>(imm5) | Rm(rm));
2250 }
2251 
2252 // SVEIntArithmeticUnpredicated.
2253 
add(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2254 void Assembler::add(const ZRegister& zd,
2255                     const ZRegister& zn,
2256                     const ZRegister& zm) {
2257   // ADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2258   //  0000 0100 ..1. .... 0000 00.. .... ....
2259   //  size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
2260 
2261   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2262   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2263 
2264   Emit(ADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2265 }
2266 
sqadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2267 void Assembler::sqadd(const ZRegister& zd,
2268                       const ZRegister& zn,
2269                       const ZRegister& zm) {
2270   // SQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2271   //  0000 0100 ..1. .... 0001 00.. .... ....
2272   //  size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>
2273 
2274   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2275   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2276 
2277   Emit(SQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2278 }
2279 
sqsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2280 void Assembler::sqsub(const ZRegister& zd,
2281                       const ZRegister& zn,
2282                       const ZRegister& zm) {
2283   // SQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2284   //  0000 0100 ..1. .... 0001 10.. .... ....
2285   //  size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>
2286 
2287   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2288   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2289 
2290   Emit(SQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2291 }
2292 
sub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2293 void Assembler::sub(const ZRegister& zd,
2294                     const ZRegister& zn,
2295                     const ZRegister& zm) {
2296   // SUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2297   //  0000 0100 ..1. .... 0000 01.. .... ....
2298   //  size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
2299 
2300   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2301   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2302 
2303   Emit(SUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2304 }
2305 
uqadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2306 void Assembler::uqadd(const ZRegister& zd,
2307                       const ZRegister& zn,
2308                       const ZRegister& zm) {
2309   // UQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2310   //  0000 0100 ..1. .... 0001 01.. .... ....
2311   //  size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>
2312 
2313   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2314   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2315 
2316   Emit(UQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2317 }
2318 
uqsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)2319 void Assembler::uqsub(const ZRegister& zd,
2320                       const ZRegister& zn,
2321                       const ZRegister& zm) {
2322   // UQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2323   //  0000 0100 ..1. .... 0001 11.. .... ....
2324   //  size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>
2325 
2326   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2327   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2328 
2329   Emit(UQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2330 }
2331 
2332 // SVEIntBinaryArithmeticPredicated.
2333 
add(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2334 void Assembler::add(const ZRegister& zd,
2335                     const PRegisterM& pg,
2336                     const ZRegister& zn,
2337                     const ZRegister& zm) {
2338   // ADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2339   //  0000 0100 ..00 0000 000. .... .... ....
2340   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2341 
2342   USE(zn);
2343   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2344   VIXL_ASSERT(zd.Is(zn));
2345   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2346 
2347   Emit(ADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2348 }
2349 
and_(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2350 void Assembler::and_(const ZRegister& zd,
2351                      const PRegisterM& pg,
2352                      const ZRegister& zn,
2353                      const ZRegister& zm) {
2354   // AND <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2355   //  0000 0100 ..01 1010 000. .... .... ....
2356   //  size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2357 
2358   USE(zn);
2359   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2360   VIXL_ASSERT(zd.Is(zn));
2361   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2362 
2363   Emit(AND_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2364 }
2365 
bic(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2366 void Assembler::bic(const ZRegister& zd,
2367                     const PRegisterM& pg,
2368                     const ZRegister& zn,
2369                     const ZRegister& zm) {
2370   // BIC <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2371   //  0000 0100 ..01 1011 000. .... .... ....
2372   //  size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2373 
2374   USE(zn);
2375   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2376   VIXL_ASSERT(zd.Is(zn));
2377   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2378 
2379   Emit(BIC_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2380 }
2381 
eor(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2382 void Assembler::eor(const ZRegister& zd,
2383                     const PRegisterM& pg,
2384                     const ZRegister& zn,
2385                     const ZRegister& zm) {
2386   // EOR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2387   //  0000 0100 ..01 1001 000. .... .... ....
2388   //  size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2389 
2390   USE(zn);
2391   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2392   VIXL_ASSERT(zd.Is(zn));
2393   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2394 
2395   Emit(EOR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2396 }
2397 
mul(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2398 void Assembler::mul(const ZRegister& zd,
2399                     const PRegisterM& pg,
2400                     const ZRegister& zn,
2401                     const ZRegister& zm) {
2402   // MUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2403   //  0000 0100 ..01 0000 000. .... .... ....
2404   //  size<23:22> | H<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2405 
2406   USE(zn);
2407   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2408   VIXL_ASSERT(zd.Is(zn));
2409   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2410 
2411   Emit(MUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2412 }
2413 
orr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2414 void Assembler::orr(const ZRegister& zd,
2415                     const PRegisterM& pg,
2416                     const ZRegister& zn,
2417                     const ZRegister& zm) {
2418   // ORR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2419   //  0000 0100 ..01 1000 000. .... .... ....
2420   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2421 
2422   USE(zn);
2423   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2424   VIXL_ASSERT(zd.Is(zn));
2425   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2426 
2427   Emit(ORR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2428 }
2429 
sabd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2430 void Assembler::sabd(const ZRegister& zd,
2431                      const PRegisterM& pg,
2432                      const ZRegister& zn,
2433                      const ZRegister& zm) {
2434   // SABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2435   //  0000 0100 ..00 1100 000. .... .... ....
2436   //  size<23:22> | opc<18:17> = 10 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2437 
2438   USE(zn);
2439   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2440   VIXL_ASSERT(zd.Is(zn));
2441   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2442 
2443   Emit(SABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2444 }
2445 
sdiv(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2446 void Assembler::sdiv(const ZRegister& zd,
2447                      const PRegisterM& pg,
2448                      const ZRegister& zn,
2449                      const ZRegister& zm) {
2450   // SDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2451   //  0000 0100 ..01 0100 000. .... .... ....
2452   //  size<23:22> | R<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2453 
2454   USE(zn);
2455   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2456   VIXL_ASSERT(zd.Is(zn));
2457   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2458   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2459 
2460   Emit(SDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2461 }
2462 
sdivr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2463 void Assembler::sdivr(const ZRegister& zd,
2464                       const PRegisterM& pg,
2465                       const ZRegister& zn,
2466                       const ZRegister& zm) {
2467   // SDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2468   //  0000 0100 ..01 0110 000. .... .... ....
2469   //  size<23:22> | R<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2470 
2471   USE(zn);
2472   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2473   VIXL_ASSERT(zd.Is(zn));
2474   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2475   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2476 
2477   Emit(SDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2478 }
2479 
smax(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2480 void Assembler::smax(const ZRegister& zd,
2481                      const PRegisterM& pg,
2482                      const ZRegister& zn,
2483                      const ZRegister& zm) {
2484   // SMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2485   //  0000 0100 ..00 1000 000. .... .... ....
2486   //  size<23:22> | opc<18:17> = 00 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2487 
2488   USE(zn);
2489   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2490   VIXL_ASSERT(zd.Is(zn));
2491   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2492 
2493   Emit(SMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2494 }
2495 
smin(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2496 void Assembler::smin(const ZRegister& zd,
2497                      const PRegisterM& pg,
2498                      const ZRegister& zn,
2499                      const ZRegister& zm) {
2500   // SMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2501   //  0000 0100 ..00 1010 000. .... .... ....
2502   //  size<23:22> | opc<18:17> = 01 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2503 
2504   USE(zn);
2505   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2506   VIXL_ASSERT(zd.Is(zn));
2507   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2508 
2509   Emit(SMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2510 }
2511 
smulh(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2512 void Assembler::smulh(const ZRegister& zd,
2513                       const PRegisterM& pg,
2514                       const ZRegister& zn,
2515                       const ZRegister& zm) {
2516   // SMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2517   //  0000 0100 ..01 0010 000. .... .... ....
2518   //  size<23:22> | H<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2519 
2520   USE(zn);
2521   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2522   VIXL_ASSERT(zd.Is(zn));
2523   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2524 
2525   Emit(SMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2526 }
2527 
sub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2528 void Assembler::sub(const ZRegister& zd,
2529                     const PRegisterM& pg,
2530                     const ZRegister& zn,
2531                     const ZRegister& zm) {
2532   // SUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2533   //  0000 0100 ..00 0001 000. .... .... ....
2534   //  size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2535 
2536   USE(zn);
2537   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2538   VIXL_ASSERT(zd.Is(zn));
2539   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2540 
2541   Emit(SUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2542 }
2543 
subr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2544 void Assembler::subr(const ZRegister& zd,
2545                      const PRegisterM& pg,
2546                      const ZRegister& zn,
2547                      const ZRegister& zm) {
2548   // SUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2549   //  0000 0100 ..00 0011 000. .... .... ....
2550   //  size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2551 
2552   USE(zn);
2553   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2554   VIXL_ASSERT(zd.Is(zn));
2555   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2556 
2557   Emit(SUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2558 }
2559 
uabd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2560 void Assembler::uabd(const ZRegister& zd,
2561                      const PRegisterM& pg,
2562                      const ZRegister& zn,
2563                      const ZRegister& zm) {
2564   // UABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2565   //  0000 0100 ..00 1101 000. .... .... ....
2566   //  size<23:22> | opc<18:17> = 10 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2567 
2568   USE(zn);
2569   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2570   VIXL_ASSERT(zd.Is(zn));
2571   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2572 
2573   Emit(UABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2574 }
2575 
udiv(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2576 void Assembler::udiv(const ZRegister& zd,
2577                      const PRegisterM& pg,
2578                      const ZRegister& zn,
2579                      const ZRegister& zm) {
2580   // UDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2581   //  0000 0100 ..01 0101 000. .... .... ....
2582   //  size<23:22> | R<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2583 
2584   USE(zn);
2585   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2586   VIXL_ASSERT(zd.Is(zn));
2587   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2588   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2589 
2590   Emit(UDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2591 }
2592 
udivr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2593 void Assembler::udivr(const ZRegister& zd,
2594                       const PRegisterM& pg,
2595                       const ZRegister& zn,
2596                       const ZRegister& zm) {
2597   // UDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2598   //  0000 0100 ..01 0111 000. .... .... ....
2599   //  size<23:22> | R<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2600 
2601   USE(zn);
2602   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2603   VIXL_ASSERT(zd.Is(zn));
2604   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2605   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2606 
2607   Emit(UDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2608 }
2609 
umax(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2610 void Assembler::umax(const ZRegister& zd,
2611                      const PRegisterM& pg,
2612                      const ZRegister& zn,
2613                      const ZRegister& zm) {
2614   // UMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2615   //  0000 0100 ..00 1001 000. .... .... ....
2616   //  size<23:22> | opc<18:17> = 00 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2617 
2618   USE(zn);
2619   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2620   VIXL_ASSERT(zd.Is(zn));
2621   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2622 
2623   Emit(UMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2624 }
2625 
umin(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2626 void Assembler::umin(const ZRegister& zd,
2627                      const PRegisterM& pg,
2628                      const ZRegister& zn,
2629                      const ZRegister& zm) {
2630   // UMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2631   //  0000 0100 ..00 1011 000. .... .... ....
2632   //  size<23:22> | opc<18:17> = 01 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2633 
2634   USE(zn);
2635   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2636   VIXL_ASSERT(zd.Is(zn));
2637   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2638 
2639   Emit(UMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2640 }
2641 
umulh(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)2642 void Assembler::umulh(const ZRegister& zd,
2643                       const PRegisterM& pg,
2644                       const ZRegister& zn,
2645                       const ZRegister& zm) {
2646   // UMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2647   //  0000 0100 ..01 0011 000. .... .... ....
2648   //  size<23:22> | H<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2649 
2650   USE(zn);
2651   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2652   VIXL_ASSERT(zd.Is(zn));
2653   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2654 
2655   Emit(UMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2656 }
2657 
2658 // SVEIntCompareScalars.
2659 
ctermeq(const Register & rn,const Register & rm)2660 void Assembler::ctermeq(const Register& rn, const Register& rm) {
2661   // CTERMEQ <R><n>, <R><m>
2662   //  0010 0101 1.1. .... 0010 00.. ...0 0000
2663   //  op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 0
2664 
2665   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2666   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2667   const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;
2668 
2669   Emit(CTERMEQ_rr | sz | Rn(rn) | Rm(rm));
2670 }
2671 
ctermne(const Register & rn,const Register & rm)2672 void Assembler::ctermne(const Register& rn, const Register& rm) {
2673   // CTERMNE <R><n>, <R><m>
2674   //  0010 0101 1.1. .... 0010 00.. ...1 0000
2675   //  op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 1
2676 
2677   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2678   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2679   const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;
2680 
2681   Emit(CTERMNE_rr | sz | Rn(rn) | Rm(rm));
2682 }
2683 
whilele(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)2684 void Assembler::whilele(const PRegisterWithLaneSize& pd,
2685                         const Register& rn,
2686                         const Register& rm) {
2687   // WHILELE <Pd>.<T>, <R><n>, <R><m>
2688   //  0010 0101 ..1. .... 000. 01.. ...1 ....
2689   //  size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |
2690   //  eq<4> = 1 | Pd<3:0>
2691 
2692   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2693   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2694   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2695 
2696   Emit(WHILELE_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2697 }
2698 
whilelo(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)2699 void Assembler::whilelo(const PRegisterWithLaneSize& pd,
2700                         const Register& rn,
2701                         const Register& rm) {
2702   // WHILELO <Pd>.<T>, <R><n>, <R><m>
2703   //  0010 0101 ..1. .... 000. 11.. ...0 ....
2704   //  size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |
2705   //  eq<4> = 0 | Pd<3:0>
2706 
2707   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2708   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2709   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2710 
2711   Emit(WHILELO_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2712 }
2713 
whilels(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)2714 void Assembler::whilels(const PRegisterWithLaneSize& pd,
2715                         const Register& rn,
2716                         const Register& rm) {
2717   // WHILELS <Pd>.<T>, <R><n>, <R><m>
2718   //  0010 0101 ..1. .... 000. 11.. ...1 ....
2719   //  size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |
2720   //  eq<4> = 1 | Pd<3:0>
2721 
2722   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2723   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2724   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2725 
2726   Emit(WHILELS_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2727 }
2728 
whilelt(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)2729 void Assembler::whilelt(const PRegisterWithLaneSize& pd,
2730                         const Register& rn,
2731                         const Register& rm) {
2732   // WHILELT <Pd>.<T>, <R><n>, <R><m>
2733   //  0010 0101 ..1. .... 000. 01.. ...0 ....
2734   //  size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |
2735   //  eq<4> = 0 | Pd<3:0>
2736 
2737   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2738   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2739   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2740 
2741   Emit(WHILELT_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2742 }
2743 
CompareVectors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm,SVEIntCompareVectorsOp op)2744 void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2745                                const PRegisterZ& pg,
2746                                const ZRegister& zn,
2747                                const ZRegister& zm,
2748                                SVEIntCompareVectorsOp op) {
2749   Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
2750 }
2751 
CompareVectors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm,SVEIntCompareSignedImmOp op)2752 void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2753                                const PRegisterZ& pg,
2754                                const ZRegister& zn,
2755                                int imm,
2756                                SVEIntCompareSignedImmOp op) {
2757   Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm));
2758 }
2759 
CompareVectors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,unsigned imm,SVEIntCompareUnsignedImmOp op)2760 void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2761                                const PRegisterZ& pg,
2762                                const ZRegister& zn,
2763                                unsigned imm,
2764                                SVEIntCompareUnsignedImmOp op) {
2765   Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) |
2766        ImmUnsignedField<20, 14>(imm));
2767 }
2768 
cmp(Condition cond,const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)2769 void Assembler::cmp(Condition cond,
2770                     const PRegisterWithLaneSize& pd,
2771                     const PRegisterZ& pg,
2772                     const ZRegister& zn,
2773                     const ZRegister& zm) {
2774   switch (cond) {
2775     case eq:
2776       cmpeq(pd, pg, zn, zm);
2777       break;
2778     case ge:
2779       cmpge(pd, pg, zn, zm);
2780       break;
2781     case gt:
2782       cmpgt(pd, pg, zn, zm);
2783       break;
2784     case le:
2785       cmple(pd, pg, zn, zm);
2786       break;
2787     case lt:
2788       cmplt(pd, pg, zn, zm);
2789       break;
2790     case ne:
2791       cmpne(pd, pg, zn, zm);
2792       break;
2793     case hi:
2794       cmphi(pd, pg, zn, zm);
2795       break;
2796     case hs:
2797       cmphs(pd, pg, zn, zm);
2798       break;
2799     case lo:
2800       cmplo(pd, pg, zn, zm);
2801       break;
2802     case ls:
2803       cmpls(pd, pg, zn, zm);
2804       break;
2805     default:
2806       VIXL_UNREACHABLE();
2807   }
2808 }
2809 
2810 // SVEIntCompareSignedImm.
2811 
cmpeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2812 void Assembler::cmpeq(const PRegisterWithLaneSize& pd,
2813                       const PRegisterZ& pg,
2814                       const ZRegister& zn,
2815                       int imm5) {
2816   // CMPEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2817   //  0010 0101 ..0. .... 100. .... ...0 ....
2818   //  size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2819   //  | ne<4> = 0 | Pd<3:0>
2820 
2821   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2822   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2823 
2824   CompareVectors(pd, pg, zn, imm5, CMPEQ_p_p_zi);
2825 }
2826 
cmpge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2827 void Assembler::cmpge(const PRegisterWithLaneSize& pd,
2828                       const PRegisterZ& pg,
2829                       const ZRegister& zn,
2830                       int imm5) {
2831   // CMPGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2832   //  0010 0101 ..0. .... 000. .... ...0 ....
2833   //  size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2834   //  | ne<4> = 0 | Pd<3:0>
2835 
2836   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2837   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2838 
2839   CompareVectors(pd, pg, zn, imm5, CMPGE_p_p_zi);
2840 }
2841 
cmpgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2842 void Assembler::cmpgt(const PRegisterWithLaneSize& pd,
2843                       const PRegisterZ& pg,
2844                       const ZRegister& zn,
2845                       int imm5) {
2846   // CMPGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2847   //  0010 0101 ..0. .... 000. .... ...1 ....
2848   //  size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2849   //  | ne<4> = 1 | Pd<3:0>
2850 
2851   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2852   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2853 
2854   CompareVectors(pd, pg, zn, imm5, CMPGT_p_p_zi);
2855 }
2856 
cmple(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2857 void Assembler::cmple(const PRegisterWithLaneSize& pd,
2858                       const PRegisterZ& pg,
2859                       const ZRegister& zn,
2860                       int imm5) {
2861   // CMPLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2862   //  0010 0101 ..0. .... 001. .... ...1 ....
2863   //  size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>
2864   //  | ne<4> = 1 | Pd<3:0>
2865 
2866   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2867   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2868 
2869   CompareVectors(pd, pg, zn, imm5, CMPLE_p_p_zi);
2870 }
2871 
cmplt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2872 void Assembler::cmplt(const PRegisterWithLaneSize& pd,
2873                       const PRegisterZ& pg,
2874                       const ZRegister& zn,
2875                       int imm5) {
2876   // CMPLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2877   //  0010 0101 ..0. .... 001. .... ...0 ....
2878   //  size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>
2879   //  | ne<4> = 0 | Pd<3:0>
2880 
2881   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2882   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2883 
2884   CompareVectors(pd, pg, zn, imm5, CMPLT_p_p_zi);
2885 }
2886 
cmpne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,int imm5)2887 void Assembler::cmpne(const PRegisterWithLaneSize& pd,
2888                       const PRegisterZ& pg,
2889                       const ZRegister& zn,
2890                       int imm5) {
2891   // CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2892   //  0010 0101 ..0. .... 100. .... ...1 ....
2893   //  size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2894   //  | ne<4> = 1 | Pd<3:0>
2895 
2896   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2897   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2898 
2899   CompareVectors(pd, pg, zn, imm5, CMPNE_p_p_zi);
2900 }
2901 
2902 // SVEIntCompareUnsignedImm.
2903 
cmphi(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,unsigned imm7)2904 void Assembler::cmphi(const PRegisterWithLaneSize& pd,
2905                       const PRegisterZ& pg,
2906                       const ZRegister& zn,
2907                       unsigned imm7) {
2908   // CMPHI <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2909   //  0010 0100 ..1. .... ..0. .... ...1 ....
2910   //  size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
2911   //  Pd<3:0>
2912 
2913   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2914   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2915 
2916   CompareVectors(pd, pg, zn, imm7, CMPHI_p_p_zi);
2917 }
2918 
cmphs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,unsigned imm7)2919 void Assembler::cmphs(const PRegisterWithLaneSize& pd,
2920                       const PRegisterZ& pg,
2921                       const ZRegister& zn,
2922                       unsigned imm7) {
2923   // CMPHS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2924   //  0010 0100 ..1. .... ..0. .... ...0 ....
2925   //  size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
2926   //  Pd<3:0>
2927 
2928   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2929   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2930 
2931   CompareVectors(pd, pg, zn, imm7, CMPHS_p_p_zi);
2932 }
2933 
cmplo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,unsigned imm7)2934 void Assembler::cmplo(const PRegisterWithLaneSize& pd,
2935                       const PRegisterZ& pg,
2936                       const ZRegister& zn,
2937                       unsigned imm7) {
2938   // CMPLO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2939   //  0010 0100 ..1. .... ..1. .... ...0 ....
2940   //  size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
2941   //  Pd<3:0>
2942 
2943   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2944   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2945 
2946   CompareVectors(pd, pg, zn, imm7, CMPLO_p_p_zi);
2947 }
2948 
cmpls(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,unsigned imm7)2949 void Assembler::cmpls(const PRegisterWithLaneSize& pd,
2950                       const PRegisterZ& pg,
2951                       const ZRegister& zn,
2952                       unsigned imm7) {
2953   // CMPLS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2954   //  0010 0100 ..1. .... ..1. .... ...1 ....
2955   //  size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
2956   //  Pd<3:0>
2957 
2958   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2959   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2960 
2961   CompareVectors(pd, pg, zn, imm7, CMPLS_p_p_zi);
2962 }
2963 
2964 // SVEIntCompareVectors.
2965 
2966 // This prototype maps to 2 instruction encodings:
2967 //  CMPEQ_p_p_zw
2968 //  CMPEQ_p_p_zz
cmpeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)2969 void Assembler::cmpeq(const PRegisterWithLaneSize& pd,
2970                       const PRegisterZ& pg,
2971                       const ZRegister& zn,
2972                       const ZRegister& zm) {
2973   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2974   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2975   SVEIntCompareVectorsOp op = CMPEQ_p_p_zz;
2976   if (!AreSameLaneSize(zn, zm)) {
2977     VIXL_ASSERT(zm.IsLaneSizeD());
2978     op = CMPEQ_p_p_zw;
2979   }
2980   CompareVectors(pd, pg, zn, zm, op);
2981 }
2982 
2983 // This prototype maps to 2 instruction encodings:
2984 //  CMPGE_p_p_zw
2985 //  CMPGE_p_p_zz
cmpge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)2986 void Assembler::cmpge(const PRegisterWithLaneSize& pd,
2987                       const PRegisterZ& pg,
2988                       const ZRegister& zn,
2989                       const ZRegister& zm) {
2990   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2991   VIXL_ASSERT(AreSameLaneSize(pd, zn));
2992   SVEIntCompareVectorsOp op = CMPGE_p_p_zz;
2993   if (!AreSameLaneSize(zn, zm)) {
2994     VIXL_ASSERT(zm.IsLaneSizeD());
2995     op = CMPGE_p_p_zw;
2996   }
2997   CompareVectors(pd, pg, zn, zm, op);
2998 }
2999 
3000 // This prototype maps to 2 instruction encodings:
3001 //  CMPGT_p_p_zw
3002 //  CMPGT_p_p_zz
cmpgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3003 void Assembler::cmpgt(const PRegisterWithLaneSize& pd,
3004                       const PRegisterZ& pg,
3005                       const ZRegister& zn,
3006                       const ZRegister& zm) {
3007   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3008   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3009   SVEIntCompareVectorsOp op = CMPGT_p_p_zz;
3010   if (!AreSameLaneSize(zn, zm)) {
3011     VIXL_ASSERT(zm.IsLaneSizeD());
3012     op = CMPGT_p_p_zw;
3013   }
3014   CompareVectors(pd, pg, zn, zm, op);
3015 }
3016 
3017 // This prototype maps to 2 instruction encodings:
3018 //  CMPHI_p_p_zw
3019 //  CMPHI_p_p_zz
cmphi(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3020 void Assembler::cmphi(const PRegisterWithLaneSize& pd,
3021                       const PRegisterZ& pg,
3022                       const ZRegister& zn,
3023                       const ZRegister& zm) {
3024   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3025   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3026   SVEIntCompareVectorsOp op = CMPHI_p_p_zz;
3027   if (!AreSameLaneSize(zn, zm)) {
3028     VIXL_ASSERT(zm.IsLaneSizeD());
3029     op = CMPHI_p_p_zw;
3030   }
3031   CompareVectors(pd, pg, zn, zm, op);
3032 }
3033 
3034 // This prototype maps to 2 instruction encodings:
3035 //  CMPHS_p_p_zw
3036 //  CMPHS_p_p_zz
cmphs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3037 void Assembler::cmphs(const PRegisterWithLaneSize& pd,
3038                       const PRegisterZ& pg,
3039                       const ZRegister& zn,
3040                       const ZRegister& zm) {
3041   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3042   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3043   SVEIntCompareVectorsOp op = CMPHS_p_p_zz;
3044   if (!AreSameLaneSize(zn, zm)) {
3045     VIXL_ASSERT(zm.IsLaneSizeD());
3046     op = CMPHS_p_p_zw;
3047   }
3048   CompareVectors(pd, pg, zn, zm, op);
3049 }
3050 
cmple(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3051 void Assembler::cmple(const PRegisterWithLaneSize& pd,
3052                       const PRegisterZ& pg,
3053                       const ZRegister& zn,
3054                       const ZRegister& zm) {
3055   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3056   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3057   if (AreSameLaneSize(zn, zm)) {
3058     cmpge(pd, pg, zm, zn);
3059     return;
3060   }
3061   VIXL_ASSERT(zm.IsLaneSizeD());
3062   VIXL_ASSERT(!zn.IsLaneSizeD());
3063 
3064   CompareVectors(pd, pg, zn, zm, CMPLE_p_p_zw);
3065 }
3066 
cmplo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3067 void Assembler::cmplo(const PRegisterWithLaneSize& pd,
3068                       const PRegisterZ& pg,
3069                       const ZRegister& zn,
3070                       const ZRegister& zm) {
3071   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3072   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3073   if (AreSameLaneSize(zn, zm)) {
3074     cmphi(pd, pg, zm, zn);
3075     return;
3076   }
3077   VIXL_ASSERT(zm.IsLaneSizeD());
3078   VIXL_ASSERT(!zn.IsLaneSizeD());
3079 
3080   CompareVectors(pd, pg, zn, zm, CMPLO_p_p_zw);
3081 }
3082 
cmpls(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3083 void Assembler::cmpls(const PRegisterWithLaneSize& pd,
3084                       const PRegisterZ& pg,
3085                       const ZRegister& zn,
3086                       const ZRegister& zm) {
3087   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3088   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3089   if (AreSameLaneSize(zn, zm)) {
3090     cmphs(pd, pg, zm, zn);
3091     return;
3092   }
3093   VIXL_ASSERT(zm.IsLaneSizeD());
3094   VIXL_ASSERT(!zn.IsLaneSizeD());
3095 
3096   CompareVectors(pd, pg, zn, zm, CMPLS_p_p_zw);
3097 }
3098 
cmplt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3099 void Assembler::cmplt(const PRegisterWithLaneSize& pd,
3100                       const PRegisterZ& pg,
3101                       const ZRegister& zn,
3102                       const ZRegister& zm) {
3103   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3104   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3105   if (AreSameLaneSize(zn, zm)) {
3106     cmpgt(pd, pg, zm, zn);
3107     return;
3108   }
3109   VIXL_ASSERT(zm.IsLaneSizeD());
3110   VIXL_ASSERT(!zn.IsLaneSizeD());
3111 
3112   CompareVectors(pd, pg, zn, zm, CMPLT_p_p_zw);
3113 }
3114 
3115 // This prototype maps to 2 instruction encodings:
3116 //  CMPNE_p_p_zw
3117 //  CMPNE_p_p_zz
cmpne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3118 void Assembler::cmpne(const PRegisterWithLaneSize& pd,
3119                       const PRegisterZ& pg,
3120                       const ZRegister& zn,
3121                       const ZRegister& zm) {
3122   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3123   VIXL_ASSERT(AreSameLaneSize(pd, zn));
3124   SVEIntCompareVectorsOp op = CMPNE_p_p_zz;
3125   if (!AreSameLaneSize(zn, zm)) {
3126     VIXL_ASSERT(zm.IsLaneSizeD());
3127     op = CMPNE_p_p_zw;
3128   }
3129   CompareVectors(pd, pg, zn, zm, op);
3130 }
3131 
3132 // SVEIntMiscUnpredicated.
3133 
fexpa(const ZRegister & zd,const ZRegister & zn)3134 void Assembler::fexpa(const ZRegister& zd, const ZRegister& zn) {
3135   // FEXPA <Zd>.<T>, <Zn>.<T>
3136   //  0000 0100 ..10 0000 1011 10.. .... ....
3137   //  size<23:22> | opc<20:16> = 00000 | Zn<9:5> | Zd<4:0>
3138 
3139   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3140   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3141   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3142 
3143   Emit(FEXPA_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
3144 }
3145 
ftssel(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)3146 void Assembler::ftssel(const ZRegister& zd,
3147                        const ZRegister& zn,
3148                        const ZRegister& zm) {
3149   // FTSSEL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
3150   //  0000 0100 ..1. .... 1011 00.. .... ....
3151   //  size<23:22> | Zm<20:16> | op<10> = 0 | Zn<9:5> | Zd<4:0>
3152 
3153   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3154   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
3155   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3156 
3157   Emit(FTSSEL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
3158 }
3159 
movprfx(const ZRegister & zd,const ZRegister & zn)3160 void Assembler::movprfx(const ZRegister& zd, const ZRegister& zn) {
3161   // MOVPRFX <Zd>, <Zn>
3162   //  0000 0100 0010 0000 1011 11.. .... ....
3163   //  opc<23:22> = 00 | opc2<20:16> = 00000 | Zn<9:5> | Zd<4:0>
3164 
3165   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3166   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3167 
3168   Emit(MOVPRFX_z_z | Rd(zd) | Rn(zn));
3169 }
3170 
3171 // SVEIntMulAddPredicated.
3172 
mad(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)3173 void Assembler::mad(const ZRegister& zdn,
3174                     const PRegisterM& pg,
3175                     const ZRegister& zm,
3176                     const ZRegister& za) {
3177   // MAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
3178   //  0000 0100 ..0. .... 110. .... .... ....
3179   //  size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Za<9:5> | Zdn<4:0>
3180 
3181   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3182   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
3183 
3184   Emit(MAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));
3185 }
3186 
mla(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)3187 void Assembler::mla(const ZRegister& zda,
3188                     const PRegisterM& pg,
3189                     const ZRegister& zn,
3190                     const ZRegister& zm) {
3191   // MLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
3192   //  0000 0100 ..0. .... 010. .... .... ....
3193   //  size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Zn<9:5> | Zda<4:0>
3194 
3195   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3196   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
3197 
3198   Emit(MLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
3199 }
3200 
mls(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)3201 void Assembler::mls(const ZRegister& zda,
3202                     const PRegisterM& pg,
3203                     const ZRegister& zn,
3204                     const ZRegister& zm) {
3205   // MLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
3206   //  0000 0100 ..0. .... 011. .... .... ....
3207   //  size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Zn<9:5> | Zda<4:0>
3208 
3209   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3210   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
3211 
3212   Emit(MLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
3213 }
3214 
msb(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)3215 void Assembler::msb(const ZRegister& zdn,
3216                     const PRegisterM& pg,
3217                     const ZRegister& zm,
3218                     const ZRegister& za) {
3219   // MSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
3220   //  0000 0100 ..0. .... 111. .... .... ....
3221   //  size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Za<9:5> | Zdn<4:0>
3222 
3223   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3224   VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
3225 
3226   Emit(MSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));
3227 }
3228 
3229 // SVEIntMulAddUnpredicated.
3230 
sdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)3231 void Assembler::sdot(const ZRegister& zda,
3232                      const ZRegister& zn,
3233                      const ZRegister& zm) {
3234   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3235   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
3236   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
3237   VIXL_ASSERT(AreSameLaneSize(zm, zn));
3238 
3239   Emit(SDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
3240 }
3241 
udot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)3242 void Assembler::udot(const ZRegister& zda,
3243                      const ZRegister& zn,
3244                      const ZRegister& zm) {
3245   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3246   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
3247   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
3248   VIXL_ASSERT(AreSameLaneSize(zm, zn));
3249 
3250   Emit(UDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
3251 }
3252 
3253 // SVEIntReduction.
3254 
andv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3255 void Assembler::andv(const VRegister& vd,
3256                      const PRegister& pg,
3257                      const ZRegister& zn) {
3258   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3259   VIXL_ASSERT(vd.IsScalar());
3260 
3261   Emit(ANDV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3262 }
3263 
eorv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3264 void Assembler::eorv(const VRegister& vd,
3265                      const PRegister& pg,
3266                      const ZRegister& zn) {
3267   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3268   VIXL_ASSERT(vd.IsScalar());
3269 
3270   Emit(EORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3271 }
3272 
movprfx(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)3273 void Assembler::movprfx(const ZRegister& zd,
3274                         const PRegister& pg,
3275                         const ZRegister& zn) {
3276   // MOVPRFX <Zd>.<T>, <Pg>/<ZM>, <Zn>.<T>
3277   //  0000 0100 ..01 000. 001. .... .... ....
3278   //  size<23:22> | opc<18:17> = 00 | M<16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
3279 
3280   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3281   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3282   VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
3283   VIXL_ASSERT(!pg.HasLaneSize());
3284 
3285   Instr m = pg.IsMerging() ? 0x00010000 : 0x00000000;
3286   Emit(MOVPRFX_z_p_z | SVESize(zd) | m | Rd(zd) | PgLow8(pg) | Rn(zn));
3287 }
3288 
orv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3289 void Assembler::orv(const VRegister& vd,
3290                     const PRegister& pg,
3291                     const ZRegister& zn) {
3292   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3293   VIXL_ASSERT(vd.IsScalar());
3294 
3295   Emit(ORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3296 }
3297 
saddv(const VRegister & dd,const PRegister & pg,const ZRegister & zn)3298 void Assembler::saddv(const VRegister& dd,
3299                       const PRegister& pg,
3300                       const ZRegister& zn) {
3301   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3302   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kDRegSizeInBytes);
3303 
3304   Emit(SADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));
3305 }
3306 
smaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3307 void Assembler::smaxv(const VRegister& vd,
3308                       const PRegister& pg,
3309                       const ZRegister& zn) {
3310   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3311   VIXL_ASSERT(vd.IsScalar());
3312 
3313   Emit(SMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3314 }
3315 
sminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3316 void Assembler::sminv(const VRegister& vd,
3317                       const PRegister& pg,
3318                       const ZRegister& zn) {
3319   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3320   VIXL_ASSERT(vd.IsScalar());
3321 
3322   Emit(SMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3323 }
3324 
uaddv(const VRegister & dd,const PRegister & pg,const ZRegister & zn)3325 void Assembler::uaddv(const VRegister& dd,
3326                       const PRegister& pg,
3327                       const ZRegister& zn) {
3328   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3329 
3330   Emit(UADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));
3331 }
3332 
umaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3333 void Assembler::umaxv(const VRegister& vd,
3334                       const PRegister& pg,
3335                       const ZRegister& zn) {
3336   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3337   VIXL_ASSERT(vd.IsScalar());
3338 
3339   Emit(UMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3340 }
3341 
uminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3342 void Assembler::uminv(const VRegister& vd,
3343                       const PRegister& pg,
3344                       const ZRegister& zn) {
3345   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3346   VIXL_ASSERT(vd.IsScalar());
3347 
3348   Emit(UMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3349 }
3350 
3351 // SVEIntUnaryArithmeticPredicated.
3352 
abs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3353 void Assembler::abs(const ZRegister& zd,
3354                     const PRegisterM& pg,
3355                     const ZRegister& zn) {
3356   // ABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3357   //  0000 0100 ..01 0110 101. .... .... ....
3358   //  size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3359 
3360   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3361   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3362 
3363   Emit(ABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3364 }
3365 
cls(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3366 void Assembler::cls(const ZRegister& zd,
3367                     const PRegisterM& pg,
3368                     const ZRegister& zn) {
3369   // CLS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3370   //  0000 0100 ..01 1000 101. .... .... ....
3371   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3372 
3373   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3374   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3375 
3376   Emit(CLS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3377 }
3378 
clz(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3379 void Assembler::clz(const ZRegister& zd,
3380                     const PRegisterM& pg,
3381                     const ZRegister& zn) {
3382   // CLZ <Zd>.<T>, <Pg>/M, <Zn>.<T>
3383   //  0000 0100 ..01 1001 101. .... .... ....
3384   //  size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3385 
3386   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3387   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3388 
3389   Emit(CLZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3390 }
3391 
cnot(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3392 void Assembler::cnot(const ZRegister& zd,
3393                      const PRegisterM& pg,
3394                      const ZRegister& zn) {
3395   // CNOT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3396   //  0000 0100 ..01 1011 101. .... .... ....
3397   //  size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3398 
3399   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3400   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3401 
3402   Emit(CNOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3403 }
3404 
cnt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3405 void Assembler::cnt(const ZRegister& zd,
3406                     const PRegisterM& pg,
3407                     const ZRegister& zn) {
3408   // CNT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3409   //  0000 0100 ..01 1010 101. .... .... ....
3410   //  size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3411 
3412   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3413   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3414 
3415   Emit(CNT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3416 }
3417 
fabs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3418 void Assembler::fabs(const ZRegister& zd,
3419                      const PRegisterM& pg,
3420                      const ZRegister& zn) {
3421   // FABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3422   //  0000 0100 ..01 1100 101. .... .... ....
3423   //  size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3424 
3425   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3426   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3427   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3428 
3429   Emit(FABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3430 }
3431 
fneg(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3432 void Assembler::fneg(const ZRegister& zd,
3433                      const PRegisterM& pg,
3434                      const ZRegister& zn) {
3435   // FNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
3436   //  0000 0100 ..01 1101 101. .... .... ....
3437   //  size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3438 
3439   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3440   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3441   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3442 
3443   Emit(FNEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3444 }
3445 
neg(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3446 void Assembler::neg(const ZRegister& zd,
3447                     const PRegisterM& pg,
3448                     const ZRegister& zn) {
3449   // NEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
3450   //  0000 0100 ..01 0111 101. .... .... ....
3451   //  size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3452 
3453   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3454   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3455 
3456   Emit(NEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3457 }
3458 
not_(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3459 void Assembler::not_(const ZRegister& zd,
3460                      const PRegisterM& pg,
3461                      const ZRegister& zn) {
3462   // NOT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3463   //  0000 0100 ..01 1110 101. .... .... ....
3464   //  size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3465 
3466   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3467   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3468 
3469   Emit(NOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3470 }
3471 
sxtb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3472 void Assembler::sxtb(const ZRegister& zd,
3473                      const PRegisterM& pg,
3474                      const ZRegister& zn) {
3475   // SXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>
3476   //  0000 0100 ..01 0000 101. .... .... ....
3477   //  size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3478 
3479   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3480   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3481   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);
3482 
3483   Emit(SXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3484 }
3485 
sxth(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3486 void Assembler::sxth(const ZRegister& zd,
3487                      const PRegisterM& pg,
3488                      const ZRegister& zn) {
3489   // SXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>
3490   //  0000 0100 ..01 0010 101. .... .... ....
3491   //  size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3492 
3493   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3494   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3495   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);
3496 
3497   Emit(SXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3498 }
3499 
sxtw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3500 void Assembler::sxtw(const ZRegister& zd,
3501                      const PRegisterM& pg,
3502                      const ZRegister& zn) {
3503   // SXTW <Zd>.D, <Pg>/M, <Zn>.D
3504   //  0000 0100 ..01 0100 101. .... .... ....
3505   //  size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3506 
3507   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3508   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3509   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);
3510 
3511   Emit(SXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3512 }
3513 
uxtb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3514 void Assembler::uxtb(const ZRegister& zd,
3515                      const PRegisterM& pg,
3516                      const ZRegister& zn) {
3517   // UXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>
3518   //  0000 0100 ..01 0001 101. .... .... ....
3519   //  size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3520 
3521   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3522   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3523   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);
3524 
3525   Emit(UXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3526 }
3527 
uxth(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3528 void Assembler::uxth(const ZRegister& zd,
3529                      const PRegisterM& pg,
3530                      const ZRegister& zn) {
3531   // UXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>
3532   //  0000 0100 ..01 0011 101. .... .... ....
3533   //  size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3534 
3535   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3536   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3537   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);
3538 
3539   Emit(UXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3540 }
3541 
uxtw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3542 void Assembler::uxtw(const ZRegister& zd,
3543                      const PRegisterM& pg,
3544                      const ZRegister& zn) {
3545   // UXTW <Zd>.D, <Pg>/M, <Zn>.D
3546   //  0000 0100 ..01 0101 101. .... .... ....
3547   //  size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3548 
3549   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3550   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3551   VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);
3552 
3553   Emit(UXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3554 }
3555 
3556 // SVEIntWideImmPredicated.
3557 
cpy(const ZRegister & zd,const PRegister & pg,int imm8,int shift)3558 void Assembler::cpy(const ZRegister& zd,
3559                     const PRegister& pg,
3560                     int imm8,
3561                     int shift) {
3562   // CPY <Zd>.<T>, <Pg>/<ZM>, #<imm>{, <shift>}
3563   //  0000 0101 ..01 .... 0... .... .... ....
3564   //  size<23:22> | Pg<19:16> | M<14> | sh<13> | imm8<12:5> | Zd<4:0>
3565 
3566   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3567   VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
3568 
3569   ResolveSVEImm8Shift(&imm8, &shift);
3570 
3571   Instr sh = (shift > 0) ? (1 << 13) : 0;
3572   Instr m = pg.IsMerging() ? (1 << 14) : 0;
3573   Emit(CPY_z_p_i | m | sh | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) |
3574        ImmField<12, 5>(imm8));
3575 }
3576 
fcpy(const ZRegister & zd,const PRegisterM & pg,double imm)3577 void Assembler::fcpy(const ZRegister& zd, const PRegisterM& pg, double imm) {
3578   // FCPY <Zd>.<T>, <Pg>/M, #<const>
3579   //  0000 0101 ..01 .... 110. .... .... ....
3580   //  size<23:22> | Pg<19:16> | imm8<12:5> | Zd<4:0>
3581 
3582   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3583   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3584 
3585   Instr imm_field = ImmUnsignedField<12, 5>(FP64ToImm8(imm));
3586   Emit(FCPY_z_p_i | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) | imm_field);
3587 }
3588 
3589 // SVEIntAddSubtractImmUnpredicated.
3590 
SVEIntAddSubtractImmUnpredicatedHelper(SVEIntAddSubtractImm_UnpredicatedOp op,const ZRegister & zd,int imm8,int shift)3591 void Assembler::SVEIntAddSubtractImmUnpredicatedHelper(
3592     SVEIntAddSubtractImm_UnpredicatedOp op,
3593     const ZRegister& zd,
3594     int imm8,
3595     int shift) {
3596   if (shift < 0) {
3597     VIXL_ASSERT(shift == -1);
3598     // Derive the shift amount from the immediate.
3599     if (IsUint8(imm8)) {
3600       shift = 0;
3601     } else if (IsUint16(imm8) && ((imm8 % 256) == 0)) {
3602       imm8 /= 256;
3603       shift = 8;
3604     }
3605   }
3606 
3607   VIXL_ASSERT(IsUint8(imm8));
3608   VIXL_ASSERT((shift == 0) || (shift == 8));
3609 
3610   Instr shift_bit = (shift > 0) ? (1 << 13) : 0;
3611   Emit(op | SVESize(zd) | Rd(zd) | shift_bit | ImmUnsignedField<12, 5>(imm8));
3612 }
3613 
add(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3614 void Assembler::add(const ZRegister& zd,
3615                     const ZRegister& zn,
3616                     int imm8,
3617                     int shift) {
3618   // ADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3619   //  0010 0101 ..10 0000 11.. .... .... ....
3620   //  size<23:22> | opc<18:16> = 000 | sh<13> | imm8<12:5> | Zdn<4:0>
3621 
3622   USE(zn);
3623   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3624   VIXL_ASSERT(zd.Is(zn));
3625   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3626 
3627   SVEIntAddSubtractImmUnpredicatedHelper(ADD_z_zi, zd, imm8, shift);
3628 }
3629 
dup(const ZRegister & zd,int imm8,int shift)3630 void Assembler::dup(const ZRegister& zd, int imm8, int shift) {
3631   // DUP <Zd>.<T>, #<imm>{, <shift>}
3632   //  0010 0101 ..11 1000 11.. .... .... ....
3633   //  size<23:22> | opc<18:17> = 00 | sh<13> | imm8<12:5> | Zd<4:0>
3634 
3635   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3636 
3637   ResolveSVEImm8Shift(&imm8, &shift);
3638   VIXL_ASSERT((shift < 8) || !zd.IsLaneSizeB());
3639 
3640   Instr shift_bit = (shift > 0) ? (1 << 13) : 0;
3641   Emit(DUP_z_i | SVESize(zd) | Rd(zd) | shift_bit | ImmField<12, 5>(imm8));
3642 }
3643 
fdup(const ZRegister & zd,double imm)3644 void Assembler::fdup(const ZRegister& zd, double imm) {
3645   // FDUP <Zd>.<T>, #<const>
3646   //  0010 0101 ..11 1001 110. .... .... ....
3647   //  size<23:22> | opc<18:17> = 00 | o2<13> = 0 | imm8<12:5> | Zd<4:0>
3648 
3649   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3650   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3651 
3652   Instr encoded_imm = FP64ToImm8(imm) << 5;
3653   Emit(FDUP_z_i | SVESize(zd) | encoded_imm | Rd(zd));
3654 }
3655 
mul(const ZRegister & zd,const ZRegister & zn,int imm8)3656 void Assembler::mul(const ZRegister& zd, const ZRegister& zn, int imm8) {
3657   // MUL <Zdn>.<T>, <Zdn>.<T>, #<imm>
3658   //  0010 0101 ..11 0000 110. .... .... ....
3659   //  size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3660 
3661   USE(zn);
3662   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3663   VIXL_ASSERT(zd.Is(zn));
3664   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3665 
3666   Emit(MUL_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3667 }
3668 
smax(const ZRegister & zd,const ZRegister & zn,int imm8)3669 void Assembler::smax(const ZRegister& zd, const ZRegister& zn, int imm8) {
3670   // SMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>
3671   //  0010 0101 ..10 1000 110. .... .... ....
3672   //  size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3673 
3674   USE(zn);
3675   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3676   VIXL_ASSERT(zd.Is(zn));
3677   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3678 
3679   Emit(SMAX_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3680 }
3681 
smin(const ZRegister & zd,const ZRegister & zn,int imm8)3682 void Assembler::smin(const ZRegister& zd, const ZRegister& zn, int imm8) {
3683   // SMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>
3684   //  0010 0101 ..10 1010 110. .... .... ....
3685   //  size<23:22> | opc<18:16> = 010 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3686 
3687   USE(zn);
3688   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3689   VIXL_ASSERT(zd.Is(zn));
3690   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3691 
3692   Emit(SMIN_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3693 }
3694 
sqadd(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3695 void Assembler::sqadd(const ZRegister& zd,
3696                       const ZRegister& zn,
3697                       int imm8,
3698                       int shift) {
3699   // SQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3700   //  0010 0101 ..10 0100 11.. .... .... ....
3701   //  size<23:22> | opc<18:16> = 100 | sh<13> | imm8<12:5> | Zdn<4:0>
3702 
3703   USE(zn);
3704   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3705   VIXL_ASSERT(zd.Is(zn));
3706   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3707 
3708   SVEIntAddSubtractImmUnpredicatedHelper(SQADD_z_zi, zd, imm8, shift);
3709 }
3710 
sqsub(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3711 void Assembler::sqsub(const ZRegister& zd,
3712                       const ZRegister& zn,
3713                       int imm8,
3714                       int shift) {
3715   // SQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3716   //  0010 0101 ..10 0110 11.. .... .... ....
3717   //  size<23:22> | opc<18:16> = 110 | sh<13> | imm8<12:5> | Zdn<4:0>
3718 
3719   USE(zn);
3720   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3721   VIXL_ASSERT(zd.Is(zn));
3722   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3723 
3724   SVEIntAddSubtractImmUnpredicatedHelper(SQSUB_z_zi, zd, imm8, shift);
3725 }
3726 
sub(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3727 void Assembler::sub(const ZRegister& zd,
3728                     const ZRegister& zn,
3729                     int imm8,
3730                     int shift) {
3731   // SUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3732   //  0010 0101 ..10 0001 11.. .... .... ....
3733   //  size<23:22> | opc<18:16> = 001 | sh<13> | imm8<12:5> | Zdn<4:0>
3734 
3735   USE(zn);
3736   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3737   VIXL_ASSERT(zd.Is(zn));
3738   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3739 
3740   SVEIntAddSubtractImmUnpredicatedHelper(SUB_z_zi, zd, imm8, shift);
3741 }
3742 
subr(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3743 void Assembler::subr(const ZRegister& zd,
3744                      const ZRegister& zn,
3745                      int imm8,
3746                      int shift) {
3747   // SUBR <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3748   //  0010 0101 ..10 0011 11.. .... .... ....
3749   //  size<23:22> | opc<18:16> = 011 | sh<13> | imm8<12:5> | Zdn<4:0>
3750 
3751   USE(zn);
3752   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3753   VIXL_ASSERT(zd.Is(zn));
3754   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3755 
3756   SVEIntAddSubtractImmUnpredicatedHelper(SUBR_z_zi, zd, imm8, shift);
3757 }
3758 
umax(const ZRegister & zd,const ZRegister & zn,int imm8)3759 void Assembler::umax(const ZRegister& zd, const ZRegister& zn, int imm8) {
3760   // UMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>
3761   //  0010 0101 ..10 1001 110. .... .... ....
3762   //  size<23:22> | opc<18:16> = 001 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3763 
3764   USE(zn);
3765   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3766   VIXL_ASSERT(zd.Is(zn));
3767   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3768 
3769   Emit(UMAX_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));
3770 }
3771 
umin(const ZRegister & zd,const ZRegister & zn,int imm8)3772 void Assembler::umin(const ZRegister& zd, const ZRegister& zn, int imm8) {
3773   // UMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>
3774   //  0010 0101 ..10 1011 110. .... .... ....
3775   //  size<23:22> | opc<18:16> = 011 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3776 
3777   USE(zn);
3778   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3779   VIXL_ASSERT(zd.Is(zn));
3780   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3781 
3782   Emit(UMIN_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));
3783 }
3784 
uqadd(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3785 void Assembler::uqadd(const ZRegister& zd,
3786                       const ZRegister& zn,
3787                       int imm8,
3788                       int shift) {
3789   // UQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3790   //  0010 0101 ..10 0101 11.. .... .... ....
3791   //  size<23:22> | opc<18:16> = 101 | sh<13> | imm8<12:5> | Zdn<4:0>
3792 
3793   USE(zn);
3794   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3795   VIXL_ASSERT(zd.Is(zn));
3796   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3797 
3798   SVEIntAddSubtractImmUnpredicatedHelper(UQADD_z_zi, zd, imm8, shift);
3799 }
3800 
uqsub(const ZRegister & zd,const ZRegister & zn,int imm8,int shift)3801 void Assembler::uqsub(const ZRegister& zd,
3802                       const ZRegister& zn,
3803                       int imm8,
3804                       int shift) {
3805   // UQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3806   //  0010 0101 ..10 0111 11.. .... .... ....
3807   //  size<23:22> | opc<18:16> = 111 | sh<13> | imm8<12:5> | Zdn<4:0>
3808 
3809   USE(zn);
3810   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3811   VIXL_ASSERT(zd.Is(zn));
3812   VIXL_ASSERT(AreSameLaneSize(zd, zn));
3813 
3814   SVEIntAddSubtractImmUnpredicatedHelper(UQSUB_z_zi, zd, imm8, shift);
3815 }
3816 
3817 // SVEMemLoad.
3818 
SVELdSt1Helper(unsigned msize_in_bytes_log2,const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr,bool is_signed,Instr op)3819 void Assembler::SVELdSt1Helper(unsigned msize_in_bytes_log2,
3820                                const ZRegister& zt,
3821                                const PRegister& pg,
3822                                const SVEMemOperand& addr,
3823                                bool is_signed,
3824                                Instr op) {
3825   VIXL_ASSERT(addr.IsContiguous());
3826 
3827   Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr);
3828   Instr dtype =
3829       SVEDtype(msize_in_bytes_log2, zt.GetLaneSizeInBytesLog2(), is_signed);
3830   Emit(op | mem_op | dtype | Rt(zt) | PgLow8(pg));
3831 }
3832 
SVELdSt234Helper(int num_regs,const ZRegister & zt1,const PRegister & pg,const SVEMemOperand & addr,Instr op)3833 void Assembler::SVELdSt234Helper(int num_regs,
3834                                  const ZRegister& zt1,
3835                                  const PRegister& pg,
3836                                  const SVEMemOperand& addr,
3837                                  Instr op) {
3838   VIXL_ASSERT((num_regs >= 2) && (num_regs <= 4));
3839 
3840   unsigned msize_in_bytes_log2 = zt1.GetLaneSizeInBytesLog2();
3841   Instr num = (num_regs - 1) << 21;
3842   Instr msz = msize_in_bytes_log2 << 23;
3843   Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, num_regs, addr);
3844   Emit(op | mem_op | msz | num | Rt(zt1) | PgLow8(pg));
3845 }
3846 
SVELd1Helper(unsigned msize_in_bytes_log2,const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr,bool is_signed)3847 void Assembler::SVELd1Helper(unsigned msize_in_bytes_log2,
3848                              const ZRegister& zt,
3849                              const PRegisterZ& pg,
3850                              const SVEMemOperand& addr,
3851                              bool is_signed) {
3852   VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
3853   if (is_signed) {
3854     // Sign-extension is only possible when the vector elements are larger than
3855     // the elements in memory.
3856     VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
3857   }
3858 
3859   if (addr.IsScatterGather()) {
3860     bool is_load = true;
3861     bool is_ff = false;
3862     SVEScatterGatherHelper(msize_in_bytes_log2,
3863                            zt,
3864                            pg,
3865                            addr,
3866                            is_load,
3867                            is_signed,
3868                            is_ff);
3869     return;
3870   }
3871 
3872   Instr op = 0xffffffff;
3873   if (addr.IsScalarPlusImmediate()) {
3874     op = SVEContiguousLoad_ScalarPlusImmFixed;
3875   } else if (addr.IsScalarPlusScalar()) {
3876     // Rm must not be xzr.
3877     VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
3878     op = SVEContiguousLoad_ScalarPlusScalarFixed;
3879   } else {
3880     VIXL_UNIMPLEMENTED();
3881   }
3882   SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);
3883 }
3884 
SVELdff1Helper(unsigned msize_in_bytes_log2,const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr,bool is_signed)3885 void Assembler::SVELdff1Helper(unsigned msize_in_bytes_log2,
3886                                const ZRegister& zt,
3887                                const PRegisterZ& pg,
3888                                const SVEMemOperand& addr,
3889                                bool is_signed) {
3890   VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
3891   if (is_signed) {
3892     // Sign-extension is only possible when the vector elements are larger than
3893     // the elements in memory.
3894     VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
3895   }
3896 
3897   if (addr.IsScatterGather()) {
3898     bool is_load = true;
3899     bool is_ff = true;
3900     SVEScatterGatherHelper(msize_in_bytes_log2,
3901                            zt,
3902                            pg,
3903                            addr,
3904                            is_load,
3905                            is_signed,
3906                            is_ff);
3907     return;
3908   }
3909 
3910   if (addr.IsPlainScalar()) {
3911     // SVEMemOperand(x0) is treated as a scalar-plus-immediate form ([x0, #0]).
3912     // In these instructions, we want to treat it as [x0, xzr].
3913     SVEMemOperand addr_scalar_plus_scalar(addr.GetScalarBase(), xzr);
3914     // Guard against infinite recursion.
3915     VIXL_ASSERT(!addr_scalar_plus_scalar.IsPlainScalar());
3916     SVELdff1Helper(msize_in_bytes_log2,
3917                    zt,
3918                    pg,
3919                    addr_scalar_plus_scalar,
3920                    is_signed);
3921     return;
3922   }
3923 
3924   Instr op = 0xffffffff;
3925   if (addr.IsScalarPlusScalar()) {
3926     op = SVEContiguousFirstFaultLoad_ScalarPlusScalarFixed;
3927   } else {
3928     VIXL_UNIMPLEMENTED();
3929   }
3930   SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);
3931 }
3932 
SVEScatterGatherHelper(unsigned msize_in_bytes_log2,const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr,bool is_load,bool is_signed,bool is_first_fault)3933 void Assembler::SVEScatterGatherHelper(unsigned msize_in_bytes_log2,
3934                                        const ZRegister& zt,
3935                                        const PRegister& pg,
3936                                        const SVEMemOperand& addr,
3937                                        bool is_load,
3938                                        bool is_signed,
3939                                        bool is_first_fault) {
3940   VIXL_ASSERT(addr.IsScatterGather());
3941   VIXL_ASSERT(zt.IsLaneSizeS() || zt.IsLaneSizeD());
3942   VIXL_ASSERT(is_load || !is_first_fault);
3943   VIXL_ASSERT(is_load || !is_signed);
3944 
3945   Instr op = 0xffffffff;
3946   if (addr.IsVectorPlusImmediate()) {
3947     VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorBase()));
3948     if (is_load) {
3949       if (zt.IsLaneSizeS()) {
3950         op = SVE32BitGatherLoad_VectorPlusImmFixed;
3951       } else {
3952         op = SVE64BitGatherLoad_VectorPlusImmFixed;
3953       }
3954     } else {
3955       if (zt.IsLaneSizeS()) {
3956         op = SVE32BitScatterStore_VectorPlusImmFixed;
3957       } else {
3958         op = SVE64BitScatterStore_VectorPlusImmFixed;
3959       }
3960     }
3961   } else {
3962     VIXL_ASSERT(addr.IsScalarPlusVector());
3963     VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorOffset()));
3964     SVEOffsetModifier mod = addr.GetOffsetModifier();
3965     if (zt.IsLaneSizeS()) {
3966       VIXL_ASSERT((mod == SVE_UXTW) || (mod == SVE_SXTW));
3967       unsigned shift_amount = addr.GetShiftAmount();
3968       if (shift_amount == 0) {
3969         if (is_load) {
3970           op = SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFixed;
3971         } else {
3972           op = SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFixed;
3973         }
3974       } else if (shift_amount == 1) {
3975         VIXL_ASSERT(msize_in_bytes_log2 == kHRegSizeInBytesLog2);
3976         if (is_load) {
3977           op = SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFixed;
3978         } else {
3979           op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;
3980         }
3981       } else {
3982         VIXL_ASSERT(shift_amount == 2);
3983         VIXL_ASSERT(msize_in_bytes_log2 == kSRegSizeInBytesLog2);
3984         if (is_load) {
3985           op = SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFixed;
3986         } else {
3987           op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;
3988         }
3989       }
3990     } else if (zt.IsLaneSizeD()) {
3991       switch (mod) {
3992         case NO_SVE_OFFSET_MODIFIER:
3993           if (is_load) {
3994             op = SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFixed;
3995           } else {
3996             op = SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFixed;
3997           }
3998           break;
3999         case SVE_LSL:
4000           if (is_load) {
4001             op = SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFixed;
4002           } else {
4003             op = SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFixed;
4004           }
4005           break;
4006         case SVE_UXTW:
4007         case SVE_SXTW: {
4008           unsigned shift_amount = addr.GetShiftAmount();
4009           if (shift_amount == 0) {
4010             if (is_load) {
4011               op =
4012                   SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;
4013             } else {
4014               op =
4015                   SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;
4016             }
4017           } else {
4018             VIXL_ASSERT(shift_amount == msize_in_bytes_log2);
4019             if (is_load) {
4020               op = SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFixed;
4021             } else {
4022               op =
4023                   SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFixed;
4024             }
4025           }
4026           break;
4027         }
4028         default:
4029           VIXL_UNIMPLEMENTED();
4030       }
4031     }
4032   }
4033 
4034   Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr, is_load);
4035   Instr msz = ImmUnsignedField<24, 23>(msize_in_bytes_log2);
4036   Instr u = (!is_load || is_signed) ? 0 : (1 << 14);
4037   Instr ff = is_first_fault ? (1 << 13) : 0;
4038   Emit(op | mem_op | msz | u | ff | Rt(zt) | PgLow8(pg));
4039 }
4040 
SVELd234Helper(int num_regs,const ZRegister & zt1,const PRegisterZ & pg,const SVEMemOperand & addr)4041 void Assembler::SVELd234Helper(int num_regs,
4042                                const ZRegister& zt1,
4043                                const PRegisterZ& pg,
4044                                const SVEMemOperand& addr) {
4045   if (addr.IsScalarPlusScalar()) {
4046     // Rm must not be xzr.
4047     VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
4048   }
4049 
4050   Instr op;
4051   if (addr.IsScalarPlusImmediate()) {
4052     op = SVELoadMultipleStructures_ScalarPlusImmFixed;
4053   } else if (addr.IsScalarPlusScalar()) {
4054     op = SVELoadMultipleStructures_ScalarPlusScalarFixed;
4055   } else {
4056     // These instructions don't support any other addressing modes.
4057     VIXL_ABORT();
4058   }
4059   SVELdSt234Helper(num_regs, zt1, pg, addr, op);
4060 }
4061 
4062 // SVEMemContiguousLoad.
4063 
4064 #define VIXL_DEFINE_LD1(MSZ, LANE_SIZE)                                  \
4065   void Assembler::ld1##MSZ(const ZRegister& zt,                          \
4066                            const PRegisterZ& pg,                         \
4067                            const SVEMemOperand& addr) {                  \
4068     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                              \
4069     SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \
4070   }
4071 #define VIXL_DEFINE_LD2(MSZ, LANE_SIZE)                 \
4072   void Assembler::ld2##MSZ(const ZRegister& zt1,        \
4073                            const ZRegister& zt2,        \
4074                            const PRegisterZ& pg,        \
4075                            const SVEMemOperand& addr) { \
4076     USE(zt2);                                           \
4077     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
4078     VIXL_ASSERT(AreConsecutive(zt1, zt2));              \
4079     VIXL_ASSERT(AreSameFormat(zt1, zt2));               \
4080     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
4081     SVELd234Helper(2, zt1, pg, addr);                   \
4082   }
4083 #define VIXL_DEFINE_LD3(MSZ, LANE_SIZE)                 \
4084   void Assembler::ld3##MSZ(const ZRegister& zt1,        \
4085                            const ZRegister& zt2,        \
4086                            const ZRegister& zt3,        \
4087                            const PRegisterZ& pg,        \
4088                            const SVEMemOperand& addr) { \
4089     USE(zt2, zt3);                                      \
4090     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
4091     VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3));         \
4092     VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3));          \
4093     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
4094     SVELd234Helper(3, zt1, pg, addr);                   \
4095   }
4096 #define VIXL_DEFINE_LD4(MSZ, LANE_SIZE)                 \
4097   void Assembler::ld4##MSZ(const ZRegister& zt1,        \
4098                            const ZRegister& zt2,        \
4099                            const ZRegister& zt3,        \
4100                            const ZRegister& zt4,        \
4101                            const PRegisterZ& pg,        \
4102                            const SVEMemOperand& addr) { \
4103     USE(zt2, zt3, zt4);                                 \
4104     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
4105     VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4));    \
4106     VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4));     \
4107     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
4108     SVELd234Helper(4, zt1, pg, addr);                   \
4109   }
4110 
4111 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD1)
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD2)4112 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD2)
4113 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD3)
4114 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD4)
4115 
4116 #define VIXL_DEFINE_LD1S(MSZ, LANE_SIZE)                                \
4117   void Assembler::ld1s##MSZ(const ZRegister& zt,                        \
4118                             const PRegisterZ& pg,                       \
4119                             const SVEMemOperand& addr) {                \
4120     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                             \
4121     SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \
4122   }
4123 VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LD1S)
4124 
4125 // SVEMem32BitGatherAndUnsizedContiguous.
4126 
4127 void Assembler::SVELd1BroadcastHelper(unsigned msize_in_bytes_log2,
4128                                       const ZRegister& zt,
4129                                       const PRegisterZ& pg,
4130                                       const SVEMemOperand& addr,
4131                                       bool is_signed) {
4132   VIXL_ASSERT(addr.IsScalarPlusImmediate());
4133   VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
4134   if (is_signed) {
4135     // Sign-extension is only possible when the vector elements are larger than
4136     // the elements in memory.
4137     VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
4138   }
4139 
4140   int64_t imm = addr.GetImmediateOffset();
4141   int divisor = 1 << msize_in_bytes_log2;
4142   VIXL_ASSERT(imm % divisor == 0);
4143   Instr dtype = SVEDtypeSplit(msize_in_bytes_log2,
4144                               zt.GetLaneSizeInBytesLog2(),
4145                               is_signed);
4146 
4147   Emit(SVELoadAndBroadcastElementFixed | dtype | RnSP(addr.GetScalarBase()) |
4148        ImmUnsignedField<21, 16>(imm / divisor) | Rt(zt) | PgLow8(pg));
4149 }
4150 
4151 // This prototype maps to 4 instruction encodings:
4152 //  LD1RB_z_p_bi_u16
4153 //  LD1RB_z_p_bi_u32
4154 //  LD1RB_z_p_bi_u64
4155 //  LD1RB_z_p_bi_u8
ld1rb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4156 void Assembler::ld1rb(const ZRegister& zt,
4157                       const PRegisterZ& pg,
4158                       const SVEMemOperand& addr) {
4159   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4160 
4161   SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, false);
4162 }
4163 
4164 // This prototype maps to 3 instruction encodings:
4165 //  LD1RH_z_p_bi_u16
4166 //  LD1RH_z_p_bi_u32
4167 //  LD1RH_z_p_bi_u64
ld1rh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4168 void Assembler::ld1rh(const ZRegister& zt,
4169                       const PRegisterZ& pg,
4170                       const SVEMemOperand& addr) {
4171   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4172 
4173   SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, false);
4174 }
4175 
4176 // This prototype maps to 2 instruction encodings:
4177 //  LD1RW_z_p_bi_u32
4178 //  LD1RW_z_p_bi_u64
ld1rw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4179 void Assembler::ld1rw(const ZRegister& zt,
4180                       const PRegisterZ& pg,
4181                       const SVEMemOperand& addr) {
4182   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4183 
4184   SVELd1BroadcastHelper(kSRegSizeInBytesLog2, zt, pg, addr, false);
4185 }
4186 
ld1rd(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4187 void Assembler::ld1rd(const ZRegister& zt,
4188                       const PRegisterZ& pg,
4189                       const SVEMemOperand& addr) {
4190   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4191 
4192   SVELd1BroadcastHelper(kDRegSizeInBytesLog2, zt, pg, addr, false);
4193 }
4194 
4195 // This prototype maps to 3 instruction encodings:
4196 //  LD1RSB_z_p_bi_s16
4197 //  LD1RSB_z_p_bi_s32
4198 //  LD1RSB_z_p_bi_s64
ld1rsb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4199 void Assembler::ld1rsb(const ZRegister& zt,
4200                        const PRegisterZ& pg,
4201                        const SVEMemOperand& addr) {
4202   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4203 
4204   SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, true);
4205 }
4206 
4207 // This prototype maps to 2 instruction encodings:
4208 //  LD1RSH_z_p_bi_s32
4209 //  LD1RSH_z_p_bi_s64
ld1rsh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4210 void Assembler::ld1rsh(const ZRegister& zt,
4211                        const PRegisterZ& pg,
4212                        const SVEMemOperand& addr) {
4213   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4214 
4215   SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, true);
4216 }
4217 
ld1rsw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4218 void Assembler::ld1rsw(const ZRegister& zt,
4219                        const PRegisterZ& pg,
4220                        const SVEMemOperand& addr) {
4221   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4222 
4223   SVELd1BroadcastHelper(kWRegSizeInBytesLog2, zt, pg, addr, true);
4224 }
4225 
ldr(const CPURegister & rt,const SVEMemOperand & addr)4226 void Assembler::ldr(const CPURegister& rt, const SVEMemOperand& addr) {
4227   // LDR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]
4228 
4229   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4230   VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());
4231   VIXL_ASSERT(addr.IsPlainScalar() ||
4232               (addr.IsScalarPlusImmediate() &&
4233                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4234   int64_t imm9 = addr.GetImmediateOffset();
4235   VIXL_ASSERT(IsInt9(imm9));
4236   Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;
4237   Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;
4238 
4239   Instr op = LDR_z_bi;
4240   if (rt.IsPRegister()) {
4241     op = LDR_p_bi;
4242   }
4243   Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);
4244 }
4245 
4246 // SVEMem64BitGather.
4247 
4248 // This prototype maps to 3 instruction encodings:
4249 //  LDFF1B_z_p_bz_d_64_unscaled
4250 //  LDFF1B_z_p_bz_d_x32_unscaled
ldff1b(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4251 void Assembler::ldff1b(const ZRegister& zt,
4252                        const PRegisterZ& pg,
4253                        const Register& xn,
4254                        const ZRegister& zm) {
4255   // LDFF1B { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]
4256   //  1100 0100 010. .... 111. .... .... ....
4257   //  msz<24:23> = 00 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4258   //  | Zt<4:0>
4259 
4260   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4261 
4262   Emit(LDFF1B_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4263 }
4264 
4265 // This prototype maps to 2 instruction encodings:
4266 //  LDFF1B_z_p_ai_d
4267 //  LDFF1B_z_p_ai_s
ldff1b(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4268 void Assembler::ldff1b(const ZRegister& zt,
4269                        const PRegisterZ& pg,
4270                        const ZRegister& zn,
4271                        int imm5) {
4272   // LDFF1B { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4273   //  1100 0100 001. .... 111. .... .... ....
4274   //  msz<24:23> = 00 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4275   //  Zn<9:5> | Zt<4:0>
4276 
4277   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4278 
4279   Emit(LDFF1B_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4280 }
4281 
4282 // This prototype maps to 4 instruction encodings:
4283 //  LDFF1D_z_p_bz_d_64_scaled
4284 //  LDFF1D_z_p_bz_d_64_unscaled
4285 //  LDFF1D_z_p_bz_d_x32_scaled
4286 //  LDFF1D_z_p_bz_d_x32_unscaled
ldff1d(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4287 void Assembler::ldff1d(const ZRegister& zt,
4288                        const PRegisterZ& pg,
4289                        const Register& xn,
4290                        const ZRegister& zm) {
4291   // LDFF1D { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #3]
4292   //  1100 0101 111. .... 111. .... .... ....
4293   //  msz<24:23> = 11 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4294   //  | Zt<4:0>
4295 
4296   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4297 
4298   Emit(LDFF1D_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4299 }
4300 
ldff1d(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4301 void Assembler::ldff1d(const ZRegister& zt,
4302                        const PRegisterZ& pg,
4303                        const ZRegister& zn,
4304                        int imm5) {
4305   // LDFF1D { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4306   //  1100 0101 101. .... 111. .... .... ....
4307   //  msz<24:23> = 11 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4308   //  Zn<9:5> | Zt<4:0>
4309 
4310   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4311 
4312   Emit(LDFF1D_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4313 }
4314 
4315 // This prototype maps to 6 instruction encodings:
4316 //  LDFF1H_z_p_bz_d_64_scaled
4317 //  LDFF1H_z_p_bz_d_64_unscaled
4318 //  LDFF1H_z_p_bz_d_x32_scaled
4319 //  LDFF1H_z_p_bz_d_x32_unscaled
ldff1h(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4320 void Assembler::ldff1h(const ZRegister& zt,
4321                        const PRegisterZ& pg,
4322                        const Register& xn,
4323                        const ZRegister& zm) {
4324   // LDFF1H { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]
4325   //  1100 0100 111. .... 111. .... .... ....
4326   //  msz<24:23> = 01 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4327   //  | Zt<4:0>
4328 
4329   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4330 
4331   Emit(LDFF1H_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4332 }
4333 
4334 // This prototype maps to 2 instruction encodings:
4335 //  LDFF1H_z_p_ai_d
4336 //  LDFF1H_z_p_ai_s
ldff1h(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4337 void Assembler::ldff1h(const ZRegister& zt,
4338                        const PRegisterZ& pg,
4339                        const ZRegister& zn,
4340                        int imm5) {
4341   // LDFF1H { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4342   //  1100 0100 101. .... 111. .... .... ....
4343   //  msz<24:23> = 01 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4344   //  Zn<9:5> | Zt<4:0>
4345 
4346   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4347 
4348   Emit(LDFF1H_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4349 }
4350 
4351 // This prototype maps to 3 instruction encodings:
4352 //  LDFF1SB_z_p_bz_d_64_unscaled
4353 //  LDFF1SB_z_p_bz_d_x32_unscaled
ldff1sb(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4354 void Assembler::ldff1sb(const ZRegister& zt,
4355                         const PRegisterZ& pg,
4356                         const Register& xn,
4357                         const ZRegister& zm) {
4358   // LDFF1SB { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]
4359   //  1100 0100 010. .... 101. .... .... ....
4360   //  msz<24:23> = 00 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4361   //  | Zt<4:0>
4362 
4363   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4364 
4365   Emit(LDFF1SB_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4366 }
4367 
4368 // This prototype maps to 2 instruction encodings:
4369 //  LDFF1SB_z_p_ai_d
4370 //  LDFF1SB_z_p_ai_s
ldff1sb(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4371 void Assembler::ldff1sb(const ZRegister& zt,
4372                         const PRegisterZ& pg,
4373                         const ZRegister& zn,
4374                         int imm5) {
4375   // LDFF1SB { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4376   //  1100 0100 001. .... 101. .... .... ....
4377   //  msz<24:23> = 00 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4378   //  Zn<9:5> | Zt<4:0>
4379 
4380   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4381 
4382   Emit(LDFF1SB_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4383        ImmField<20, 16>(imm5));
4384 }
4385 
4386 // This prototype maps to 6 instruction encodings:
4387 //  LDFF1SH_z_p_bz_d_64_scaled
4388 //  LDFF1SH_z_p_bz_d_64_unscaled
4389 //  LDFF1SH_z_p_bz_d_x32_scaled
4390 //  LDFF1SH_z_p_bz_d_x32_unscaled
ldff1sh(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4391 void Assembler::ldff1sh(const ZRegister& zt,
4392                         const PRegisterZ& pg,
4393                         const Register& xn,
4394                         const ZRegister& zm) {
4395   // LDFF1SH { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]
4396   //  1100 0100 111. .... 101. .... .... ....
4397   //  msz<24:23> = 01 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4398   //  | Zt<4:0>
4399 
4400   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4401 
4402   Emit(LDFF1SH_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4403 }
4404 
4405 // This prototype maps to 2 instruction encodings:
4406 //  LDFF1SH_z_p_ai_d
4407 //  LDFF1SH_z_p_ai_s
ldff1sh(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4408 void Assembler::ldff1sh(const ZRegister& zt,
4409                         const PRegisterZ& pg,
4410                         const ZRegister& zn,
4411                         int imm5) {
4412   // LDFF1SH { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4413   //  1100 0100 101. .... 101. .... .... ....
4414   //  msz<24:23> = 01 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4415   //  Zn<9:5> | Zt<4:0>
4416 
4417   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4418 
4419   Emit(LDFF1SH_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4420        ImmField<20, 16>(imm5));
4421 }
4422 
4423 // This prototype maps to 4 instruction encodings:
4424 //  LDFF1SW_z_p_bz_d_64_scaled
4425 //  LDFF1SW_z_p_bz_d_64_unscaled
4426 //  LDFF1SW_z_p_bz_d_x32_scaled
4427 //  LDFF1SW_z_p_bz_d_x32_unscaled
ldff1sw(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4428 void Assembler::ldff1sw(const ZRegister& zt,
4429                         const PRegisterZ& pg,
4430                         const Register& xn,
4431                         const ZRegister& zm) {
4432   // LDFF1SW { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]
4433   //  1100 0101 011. .... 101. .... .... ....
4434   //  msz<24:23> = 10 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4435   //  | Zt<4:0>
4436 
4437   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4438 
4439   Emit(LDFF1SW_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4440 }
4441 
ldff1sw(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4442 void Assembler::ldff1sw(const ZRegister& zt,
4443                         const PRegisterZ& pg,
4444                         const ZRegister& zn,
4445                         int imm5) {
4446   // LDFF1SW { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4447   //  1100 0101 001. .... 101. .... .... ....
4448   //  msz<24:23> = 10 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4449   //  Zn<9:5> | Zt<4:0>
4450 
4451   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4452 
4453   Emit(LDFF1SW_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4454        ImmField<20, 16>(imm5));
4455 }
4456 
4457 // This prototype maps to 6 instruction encodings:
4458 //  LDFF1W_z_p_bz_d_64_scaled
4459 //  LDFF1W_z_p_bz_d_64_unscaled
4460 //  LDFF1W_z_p_bz_d_x32_scaled
4461 //  LDFF1W_z_p_bz_d_x32_unscaled
ldff1w(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)4462 void Assembler::ldff1w(const ZRegister& zt,
4463                        const PRegisterZ& pg,
4464                        const Register& xn,
4465                        const ZRegister& zm) {
4466   // LDFF1W { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]
4467   //  1100 0101 011. .... 111. .... .... ....
4468   //  msz<24:23> = 10 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4469   //  | Zt<4:0>
4470 
4471   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4472 
4473   Emit(LDFF1W_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4474 }
4475 
4476 // This prototype maps to 2 instruction encodings:
4477 //  LDFF1W_z_p_ai_d
4478 //  LDFF1W_z_p_ai_s
ldff1w(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)4479 void Assembler::ldff1w(const ZRegister& zt,
4480                        const PRegisterZ& pg,
4481                        const ZRegister& zn,
4482                        int imm5) {
4483   // LDFF1W { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4484   //  1100 0101 001. .... 111. .... .... ....
4485   //  msz<24:23> = 10 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4486   //  Zn<9:5> | Zt<4:0>
4487 
4488   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4489 
4490   Emit(LDFF1W_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4491 }
4492 
SVEGatherPrefetchVectorPlusImmediateHelper(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr,int prefetch_size)4493 void Assembler::SVEGatherPrefetchVectorPlusImmediateHelper(
4494     PrefetchOperation prfop,
4495     const PRegister& pg,
4496     const SVEMemOperand& addr,
4497     int prefetch_size) {
4498   VIXL_ASSERT(addr.IsVectorPlusImmediate());
4499   ZRegister zn = addr.GetVectorBase();
4500   VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4501 
4502   Instr op = 0xffffffff;
4503   switch (prefetch_size) {
4504     case kBRegSize:
4505       op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_ai_s)
4506                             : static_cast<Instr>(PRFB_i_p_ai_d);
4507       break;
4508     case kHRegSize:
4509       op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_ai_s)
4510                             : static_cast<Instr>(PRFH_i_p_ai_d);
4511       break;
4512     case kSRegSize:
4513       op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_ai_s)
4514                             : static_cast<Instr>(PRFW_i_p_ai_d);
4515       break;
4516     case kDRegSize:
4517       op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_ai_s)
4518                             : static_cast<Instr>(PRFD_i_p_ai_d);
4519       break;
4520     default:
4521       VIXL_UNIMPLEMENTED();
4522       break;
4523   }
4524 
4525   int64_t imm5 = addr.GetImmediateOffset();
4526   Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | Rn(zn) |
4527        ImmUnsignedField<20, 16>(imm5));
4528 }
4529 
SVEGatherPrefetchScalarPlusImmediateHelper(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr,int prefetch_size)4530 void Assembler::SVEGatherPrefetchScalarPlusImmediateHelper(
4531     PrefetchOperation prfop,
4532     const PRegister& pg,
4533     const SVEMemOperand& addr,
4534     int prefetch_size) {
4535   VIXL_ASSERT(addr.IsScalarPlusImmediate());
4536   int64_t imm6 = addr.GetImmediateOffset();
4537 
4538   Instr op = 0xffffffff;
4539   switch (prefetch_size) {
4540     case kBRegSize:
4541       op = PRFB_i_p_bi_s;
4542       break;
4543     case kHRegSize:
4544       op = PRFH_i_p_bi_s;
4545       break;
4546     case kSRegSize:
4547       op = PRFW_i_p_bi_s;
4548       break;
4549     case kDRegSize:
4550       op = PRFD_i_p_bi_s;
4551       break;
4552     default:
4553       VIXL_UNIMPLEMENTED();
4554       break;
4555   }
4556 
4557   Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |
4558        RnSP(addr.GetScalarBase()) | ImmField<21, 16>(imm6));
4559 }
4560 
SVEContiguousPrefetchScalarPlusScalarHelper(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr,int prefetch_size)4561 void Assembler::SVEContiguousPrefetchScalarPlusScalarHelper(
4562     PrefetchOperation prfop,
4563     const PRegister& pg,
4564     const SVEMemOperand& addr,
4565     int prefetch_size) {
4566   VIXL_ASSERT(addr.IsScalarPlusScalar());
4567   Instr op = 0xffffffff;
4568 
4569   switch (prefetch_size) {
4570     case kBRegSize:
4571       VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);
4572       op = PRFB_i_p_br_s;
4573       break;
4574     case kHRegSize:
4575       VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4576       VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);
4577       op = PRFH_i_p_br_s;
4578       break;
4579     case kSRegSize:
4580       VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4581       VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);
4582       op = PRFW_i_p_br_s;
4583       break;
4584     case kDRegSize:
4585       VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4586       VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);
4587       op = PRFD_i_p_br_s;
4588       break;
4589     default:
4590       VIXL_UNIMPLEMENTED();
4591       break;
4592   }
4593 
4594   VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
4595   Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |
4596        RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset()));
4597 }
4598 
SVEContiguousPrefetchScalarPlusVectorHelper(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr,int prefetch_size)4599 void Assembler::SVEContiguousPrefetchScalarPlusVectorHelper(
4600     PrefetchOperation prfop,
4601     const PRegister& pg,
4602     const SVEMemOperand& addr,
4603     int prefetch_size) {
4604   VIXL_ASSERT(addr.IsScalarPlusVector());
4605   ZRegister zm = addr.GetVectorOffset();
4606   SVEOffsetModifier mod = addr.GetOffsetModifier();
4607 
4608   // All prefetch scalar-plus-vector addressing modes use a shift corresponding
4609   // to the element size.
4610   switch (prefetch_size) {
4611     case kBRegSize:
4612       VIXL_ASSERT(addr.GetShiftAmount() == kBRegSizeInBytesLog2);
4613       break;
4614     case kHRegSize:
4615       VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);
4616       break;
4617     case kSRegSize:
4618       VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);
4619       break;
4620     case kDRegSize:
4621       VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);
4622       break;
4623     default:
4624       VIXL_UNIMPLEMENTED();
4625       break;
4626   }
4627 
4628   Instr sx = 0;
4629   Instr op = 0xffffffff;
4630   if ((mod == NO_SVE_OFFSET_MODIFIER) || (mod == SVE_LSL)) {
4631     VIXL_ASSERT(zm.IsLaneSizeD());
4632 
4633     switch (prefetch_size) {
4634       case kBRegSize:
4635         VIXL_ASSERT(mod == NO_SVE_OFFSET_MODIFIER);
4636         op = PRFB_i_p_bz_d_64_scaled;
4637         break;
4638       case kHRegSize:
4639         VIXL_ASSERT(mod == SVE_LSL);
4640         op = PRFH_i_p_bz_d_64_scaled;
4641         break;
4642       case kSRegSize:
4643         VIXL_ASSERT(mod == SVE_LSL);
4644         op = PRFW_i_p_bz_d_64_scaled;
4645         break;
4646       case kDRegSize:
4647         VIXL_ASSERT(mod == SVE_LSL);
4648         op = PRFD_i_p_bz_d_64_scaled;
4649         break;
4650       default:
4651         VIXL_UNIMPLEMENTED();
4652         break;
4653     }
4654   } else {
4655     VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));
4656     VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());
4657 
4658     switch (prefetch_size) {
4659       case kBRegSize:
4660         op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_bz_s_x32_scaled)
4661                               : static_cast<Instr>(PRFB_i_p_bz_d_x32_scaled);
4662         break;
4663       case kHRegSize:
4664         op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_bz_s_x32_scaled)
4665                               : static_cast<Instr>(PRFH_i_p_bz_d_x32_scaled);
4666         break;
4667       case kSRegSize:
4668         op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_bz_s_x32_scaled)
4669                               : static_cast<Instr>(PRFW_i_p_bz_d_x32_scaled);
4670         break;
4671       case kDRegSize:
4672         op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_bz_s_x32_scaled)
4673                               : static_cast<Instr>(PRFD_i_p_bz_d_x32_scaled);
4674         break;
4675       default:
4676         VIXL_UNIMPLEMENTED();
4677         break;
4678     }
4679 
4680     if (mod == SVE_SXTW) {
4681       sx = 1 << 22;
4682     }
4683   }
4684 
4685   Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | sx |
4686        RnSP(addr.GetScalarBase()) | Rm(zm));
4687 }
4688 
SVEPrefetchHelper(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr,int prefetch_size)4689 void Assembler::SVEPrefetchHelper(PrefetchOperation prfop,
4690                                   const PRegister& pg,
4691                                   const SVEMemOperand& addr,
4692                                   int prefetch_size) {
4693   if (addr.IsVectorPlusImmediate()) {
4694     // For example:
4695     //   [z0.s, #0]
4696     SVEGatherPrefetchVectorPlusImmediateHelper(prfop, pg, addr, prefetch_size);
4697 
4698   } else if (addr.IsScalarPlusImmediate()) {
4699     // For example:
4700     //   [x0, #42, mul vl]
4701     SVEGatherPrefetchScalarPlusImmediateHelper(prfop, pg, addr, prefetch_size);
4702 
4703   } else if (addr.IsScalarPlusVector()) {
4704     // For example:
4705     //   [x0, z0.s, sxtw]
4706     SVEContiguousPrefetchScalarPlusVectorHelper(prfop, pg, addr, prefetch_size);
4707 
4708   } else if (addr.IsScalarPlusScalar()) {
4709     // For example:
4710     //   [x0, x1]
4711     SVEContiguousPrefetchScalarPlusScalarHelper(prfop, pg, addr, prefetch_size);
4712 
4713   } else {
4714     VIXL_UNIMPLEMENTED();
4715   }
4716 }
4717 
prfb(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr)4718 void Assembler::prfb(PrefetchOperation prfop,
4719                      const PRegister& pg,
4720                      const SVEMemOperand& addr) {
4721   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4722   SVEPrefetchHelper(prfop, pg, addr, kBRegSize);
4723 }
4724 
prfd(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr)4725 void Assembler::prfd(PrefetchOperation prfop,
4726                      const PRegister& pg,
4727                      const SVEMemOperand& addr) {
4728   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4729   SVEPrefetchHelper(prfop, pg, addr, kDRegSize);
4730 }
4731 
prfh(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr)4732 void Assembler::prfh(PrefetchOperation prfop,
4733                      const PRegister& pg,
4734                      const SVEMemOperand& addr) {
4735   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4736   SVEPrefetchHelper(prfop, pg, addr, kHRegSize);
4737 }
4738 
prfw(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand & addr)4739 void Assembler::prfw(PrefetchOperation prfop,
4740                      const PRegister& pg,
4741                      const SVEMemOperand& addr) {
4742   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4743   SVEPrefetchHelper(prfop, pg, addr, kSRegSize);
4744 }
4745 
SVELd1St1ScaImmHelper(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr,Instr regoffset_op,Instr immoffset_op,int imm_divisor)4746 void Assembler::SVELd1St1ScaImmHelper(const ZRegister& zt,
4747                                       const PRegister& pg,
4748                                       const SVEMemOperand& addr,
4749                                       Instr regoffset_op,
4750                                       Instr immoffset_op,
4751                                       int imm_divisor) {
4752   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4753   VIXL_ASSERT(addr.IsScalarPlusScalar() || addr.IsScalarPlusImmediate());
4754 
4755   Instr op;
4756   if (addr.IsScalarPlusScalar()) {
4757     op = regoffset_op | Rm(addr.GetScalarOffset());
4758   } else {
4759     int64_t imm = addr.GetImmediateOffset();
4760     VIXL_ASSERT(((imm % imm_divisor) == 0) && IsInt4(imm / imm_divisor));
4761     op = immoffset_op | ImmField<19, 16>(imm / imm_divisor);
4762   }
4763   Emit(op | Rt(zt) | PgLow8(pg) | RnSP(addr.GetScalarBase()));
4764 }
4765 
SVELd1VecScaHelper(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr,uint32_t msize_bytes_log2,bool is_signed)4766 void Assembler::SVELd1VecScaHelper(const ZRegister& zt,
4767                                    const PRegister& pg,
4768                                    const SVEMemOperand& addr,
4769                                    uint32_t msize_bytes_log2,
4770                                    bool is_signed) {
4771   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
4772   VIXL_ASSERT(addr.IsVectorPlusScalar());
4773   ZRegister zn = addr.GetVectorBase();
4774   VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4775   VIXL_ASSERT(AreSameLaneSize(zn, zt));
4776 
4777   uint32_t esize = zn.GetLaneSizeInBytesLog2();
4778   uint32_t b14_13 = 0;
4779   if (!is_signed) b14_13 = zn.IsLaneSizeS() ? 0x1 : 0x2;
4780 
4781   Instr op = 0x04008000;  // LDNT1 with vector plus scalar addressing mode.
4782   op |= (esize << 30) | (msize_bytes_log2 << 23) | (b14_13 << 13);
4783   Emit(op | Rt(zt) | PgLow8(pg) |
4784        SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));
4785 }
4786 
SVESt1VecScaHelper(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr,uint32_t msize_bytes_log2)4787 void Assembler::SVESt1VecScaHelper(const ZRegister& zt,
4788                                    const PRegister& pg,
4789                                    const SVEMemOperand& addr,
4790                                    uint32_t msize_bytes_log2) {
4791   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
4792   VIXL_ASSERT(addr.IsVectorPlusScalar());
4793   ZRegister zn = addr.GetVectorBase();
4794   VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4795   VIXL_ASSERT(AreSameLaneSize(zn, zt));
4796 
4797   uint32_t bit22 = zn.IsLaneSizeS() ? (1 << 22) : 0;
4798   Instr op = 0xe4002000;  // STNT1 with vector plus scalar addressing mode.
4799   op |= bit22 | (msize_bytes_log2 << 23);
4800   Emit(op | Rt(zt) | PgLow8(pg) |
4801        SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));
4802 }
4803 
4804 #define VIXL_SVE_LD1R_LIST(V)                                  \
4805   V(qb, 0, B, LD1RQB_z_p_br_contiguous, LD1RQB_z_p_bi_u8, 16)  \
4806   V(qh, 1, H, LD1RQH_z_p_br_contiguous, LD1RQH_z_p_bi_u16, 16) \
4807   V(qw, 2, S, LD1RQW_z_p_br_contiguous, LD1RQW_z_p_bi_u32, 16) \
4808   V(qd, 3, D, LD1RQD_z_p_br_contiguous, LD1RQD_z_p_bi_u64, 16) \
4809   V(ob, 0, B, 0xa4200000, 0xa4202000, 32)                      \
4810   V(oh, 1, H, 0xa4a00000, 0xa4a02000, 32)                      \
4811   V(ow, 2, S, 0xa5200000, 0xa5202000, 32)                      \
4812   V(od, 3, D, 0xa5a00000, 0xa5a02000, 32)
4813 
4814 #define VIXL_DEFINE_ASM_FUNC(FN, SH, SZ, SCA, IMM, BYTES)                    \
4815   void Assembler::ld1r##FN(const ZRegister& zt,                              \
4816                            const PRegisterZ& pg,                             \
4817                            const SVEMemOperand& addr) {                      \
4818     VIXL_ASSERT((BYTES == 16) ||                                             \
4819                 ((BYTES == 32) && (CPUHas(CPUFeatures::kSVEF64MM))));        \
4820     VIXL_ASSERT(addr.IsScalarPlusImmediate() || addr.IsEquivalentToLSL(SH)); \
4821     VIXL_ASSERT(zt.IsLaneSize##SZ());                                        \
4822     SVELd1St1ScaImmHelper(zt, pg, addr, SCA, IMM, BYTES);                    \
4823   }
4824 VIXL_SVE_LD1R_LIST(VIXL_DEFINE_ASM_FUNC)
4825 #undef VIXL_DEFINE_ASM_FUNC
4826 #undef VIXL_SVE_LD1R_LIST
4827 
4828 #define VIXL_DEFINE_LDFF1(MSZ, LANE_SIZE)                                  \
4829   void Assembler::ldff1##MSZ(const ZRegister& zt,                          \
4830                              const PRegisterZ& pg,                         \
4831                              const SVEMemOperand& addr) {                  \
4832     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                                \
4833     SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \
4834   }
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LDFF1)4835 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LDFF1)
4836 
4837 #define VIXL_DEFINE_LDFF1S(MSZ, LANE_SIZE)                                \
4838   void Assembler::ldff1s##MSZ(const ZRegister& zt,                        \
4839                               const PRegisterZ& pg,                       \
4840                               const SVEMemOperand& addr) {                \
4841     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                               \
4842     SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \
4843   }
4844 VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LDFF1S)
4845 
4846 void Assembler::ldnf1b(const ZRegister& zt,
4847                        const PRegisterZ& pg,
4848                        const SVEMemOperand& addr) {
4849   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4850   VIXL_ASSERT(addr.IsPlainRegister() ||
4851               (addr.IsScalarPlusImmediate() &&
4852                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4853 
4854   SVELdSt1Helper(0,
4855                  zt,
4856                  pg,
4857                  addr,
4858                  /* is_signed = */ false,
4859                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4860 }
4861 
ldnf1d(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4862 void Assembler::ldnf1d(const ZRegister& zt,
4863                        const PRegisterZ& pg,
4864                        const SVEMemOperand& addr) {
4865   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4866   VIXL_ASSERT(addr.IsPlainRegister() ||
4867               (addr.IsScalarPlusImmediate() &&
4868                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4869 
4870   SVELdSt1Helper(3,
4871                  zt,
4872                  pg,
4873                  addr,
4874                  /* is_signed = */ false,
4875                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4876 }
4877 
ldnf1h(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4878 void Assembler::ldnf1h(const ZRegister& zt,
4879                        const PRegisterZ& pg,
4880                        const SVEMemOperand& addr) {
4881   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4882   VIXL_ASSERT(addr.IsPlainRegister() ||
4883               (addr.IsScalarPlusImmediate() &&
4884                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4885 
4886   SVELdSt1Helper(1,
4887                  zt,
4888                  pg,
4889                  addr,
4890                  /* is_signed = */ false,
4891                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4892 }
4893 
ldnf1sb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4894 void Assembler::ldnf1sb(const ZRegister& zt,
4895                         const PRegisterZ& pg,
4896                         const SVEMemOperand& addr) {
4897   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4898   VIXL_ASSERT(addr.IsPlainRegister() ||
4899               (addr.IsScalarPlusImmediate() &&
4900                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4901 
4902   SVELdSt1Helper(0,
4903                  zt,
4904                  pg,
4905                  addr,
4906                  /* is_signed = */ true,
4907                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4908 }
4909 
ldnf1sh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4910 void Assembler::ldnf1sh(const ZRegister& zt,
4911                         const PRegisterZ& pg,
4912                         const SVEMemOperand& addr) {
4913   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4914   VIXL_ASSERT(addr.IsPlainRegister() ||
4915               (addr.IsScalarPlusImmediate() &&
4916                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4917 
4918   SVELdSt1Helper(1,
4919                  zt,
4920                  pg,
4921                  addr,
4922                  /* is_signed = */ true,
4923                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4924 }
4925 
ldnf1sw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4926 void Assembler::ldnf1sw(const ZRegister& zt,
4927                         const PRegisterZ& pg,
4928                         const SVEMemOperand& addr) {
4929   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4930   VIXL_ASSERT(addr.IsPlainRegister() ||
4931               (addr.IsScalarPlusImmediate() &&
4932                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4933 
4934   SVELdSt1Helper(2,
4935                  zt,
4936                  pg,
4937                  addr,
4938                  /* is_signed = */ true,
4939                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4940 }
4941 
ldnf1w(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4942 void Assembler::ldnf1w(const ZRegister& zt,
4943                        const PRegisterZ& pg,
4944                        const SVEMemOperand& addr) {
4945   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4946   VIXL_ASSERT(addr.IsPlainRegister() ||
4947               (addr.IsScalarPlusImmediate() &&
4948                (addr.GetOffsetModifier() == SVE_MUL_VL)));
4949 
4950   SVELdSt1Helper(2,
4951                  zt,
4952                  pg,
4953                  addr,
4954                  /* is_signed = */ false,
4955                  SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4956 }
4957 
ldnt1b(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4958 void Assembler::ldnt1b(const ZRegister& zt,
4959                        const PRegisterZ& pg,
4960                        const SVEMemOperand& addr) {
4961   VIXL_ASSERT(addr.IsPlainScalar() ||
4962               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4963               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||
4964               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
4965   if (addr.IsVectorPlusScalar()) {
4966     SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ false);
4967   } else {
4968     SVELd1St1ScaImmHelper(zt,
4969                           pg,
4970                           addr,
4971                           LDNT1B_z_p_br_contiguous,
4972                           LDNT1B_z_p_bi_contiguous);
4973   }
4974 }
4975 
ldnt1d(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4976 void Assembler::ldnt1d(const ZRegister& zt,
4977                        const PRegisterZ& pg,
4978                        const SVEMemOperand& addr) {
4979   VIXL_ASSERT(addr.IsPlainScalar() ||
4980               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4981               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||
4982               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
4983   if (addr.IsVectorPlusScalar()) {
4984     SVELd1VecScaHelper(zt, pg, addr, 3, /* is_signed = */ false);
4985   } else {
4986     SVELd1St1ScaImmHelper(zt,
4987                           pg,
4988                           addr,
4989                           LDNT1D_z_p_br_contiguous,
4990                           LDNT1D_z_p_bi_contiguous);
4991   }
4992 }
4993 
ldnt1h(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4994 void Assembler::ldnt1h(const ZRegister& zt,
4995                        const PRegisterZ& pg,
4996                        const SVEMemOperand& addr) {
4997   VIXL_ASSERT(addr.IsPlainScalar() ||
4998               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4999               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||
5000               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5001   if (addr.IsVectorPlusScalar()) {
5002     SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ false);
5003   } else {
5004     SVELd1St1ScaImmHelper(zt,
5005                           pg,
5006                           addr,
5007                           LDNT1H_z_p_br_contiguous,
5008                           LDNT1H_z_p_bi_contiguous);
5009   }
5010 }
5011 
ldnt1w(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5012 void Assembler::ldnt1w(const ZRegister& zt,
5013                        const PRegisterZ& pg,
5014                        const SVEMemOperand& addr) {
5015   VIXL_ASSERT(addr.IsPlainScalar() ||
5016               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5017               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||
5018               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5019   if (addr.IsVectorPlusScalar()) {
5020     SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ false);
5021   } else {
5022     SVELd1St1ScaImmHelper(zt,
5023                           pg,
5024                           addr,
5025                           LDNT1W_z_p_br_contiguous,
5026                           LDNT1W_z_p_bi_contiguous);
5027   }
5028 }
5029 
ldnt1sb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5030 void Assembler::ldnt1sb(const ZRegister& zt,
5031                         const PRegisterZ& pg,
5032                         const SVEMemOperand& addr) {
5033   VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5034   SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ true);
5035 }
5036 
ldnt1sh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5037 void Assembler::ldnt1sh(const ZRegister& zt,
5038                         const PRegisterZ& pg,
5039                         const SVEMemOperand& addr) {
5040   VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5041   SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ true);
5042 }
5043 
ldnt1sw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5044 void Assembler::ldnt1sw(const ZRegister& zt,
5045                         const PRegisterZ& pg,
5046                         const SVEMemOperand& addr) {
5047   VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5048   SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ true);
5049 }
5050 
SVEMemOperandHelper(unsigned msize_in_bytes_log2,int num_regs,const SVEMemOperand & addr,bool is_load)5051 Instr Assembler::SVEMemOperandHelper(unsigned msize_in_bytes_log2,
5052                                      int num_regs,
5053                                      const SVEMemOperand& addr,
5054                                      bool is_load) {
5055   VIXL_ASSERT((num_regs >= 1) && (num_regs <= 4));
5056 
5057   Instr op = 0xfffffff;
5058   if (addr.IsScalarPlusImmediate()) {
5059     VIXL_ASSERT((addr.GetImmediateOffset() == 0) || addr.IsMulVl());
5060     int64_t imm = addr.GetImmediateOffset();
5061     VIXL_ASSERT((imm % num_regs) == 0);
5062     op = RnSP(addr.GetScalarBase()) | ImmField<19, 16>(imm / num_regs);
5063 
5064   } else if (addr.IsScalarPlusScalar()) {
5065     VIXL_ASSERT(addr.GetScalarOffset().IsZero() ||
5066                 addr.IsEquivalentToLSL(msize_in_bytes_log2));
5067     op = RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset());
5068 
5069   } else if (addr.IsVectorPlusImmediate()) {
5070     ZRegister zn = addr.GetVectorBase();
5071     uint64_t imm = addr.GetImmediateOffset();
5072     VIXL_ASSERT(num_regs == 1);
5073     VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
5074     VIXL_ASSERT(IsMultiple(imm, (1 << msize_in_bytes_log2)));
5075     op = Rn(zn) | ImmUnsignedField<20, 16>(imm >> msize_in_bytes_log2);
5076   } else if (addr.IsVectorPlusScalar()) {
5077     VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);
5078     VIXL_ASSERT(addr.GetShiftAmount() == 0);
5079     ZRegister zn = addr.GetVectorBase();
5080     VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
5081     Register xm = addr.GetScalarOffset();
5082     op = Rn(zn) | Rm(xm);
5083   } else if (addr.IsScalarPlusVector()) {
5084     // We have to support several different addressing modes. Some instructions
5085     // support a subset of these, but the SVEMemOperand encoding is consistent.
5086     Register xn = addr.GetScalarBase();
5087     ZRegister zm = addr.GetVectorOffset();
5088     SVEOffsetModifier mod = addr.GetOffsetModifier();
5089     Instr modifier_bit = 1 << (is_load ? 22 : 14);
5090     Instr xs = (mod == SVE_SXTW) ? modifier_bit : 0;
5091     VIXL_ASSERT(num_regs == 1);
5092 
5093     if (mod == SVE_LSL) {
5094       // 64-bit scaled offset:            [<Xn|SP>, <Zm>.D, LSL #<shift>]
5095       VIXL_ASSERT(zm.IsLaneSizeD());
5096       VIXL_ASSERT(addr.GetShiftAmount() == msize_in_bytes_log2);
5097     } else if (mod == NO_SVE_OFFSET_MODIFIER) {
5098       // 64-bit unscaled offset:          [<Xn|SP>, <Zm>.D]
5099       VIXL_ASSERT(zm.IsLaneSizeD());
5100       VIXL_ASSERT(addr.GetShiftAmount() == 0);
5101     } else {
5102       // 32-bit scaled offset:            [<Xn|SP>, <Zm>.S, <mod> #<shift>]
5103       // 32-bit unscaled offset:          [<Xn|SP>, <Zm>.S, <mod>]
5104       // 32-bit unpacked scaled offset:   [<Xn|SP>, <Zm>.D, <mod> #<shift>]
5105       // 32-bit unpacked unscaled offset: [<Xn|SP>, <Zm>.D, <mod>]
5106       VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());
5107       VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));
5108       VIXL_ASSERT((addr.GetShiftAmount() == 0) ||
5109                   (addr.GetShiftAmount() == msize_in_bytes_log2));
5110     }
5111 
5112     // The form itself is encoded in the instruction opcode.
5113     op = RnSP(xn) | Rm(zm) | xs;
5114   } else {
5115     VIXL_UNIMPLEMENTED();
5116   }
5117 
5118   return op;
5119 }
5120 
5121 // SVEMemStore.
5122 
SVESt1Helper(unsigned msize_in_bytes_log2,const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr)5123 void Assembler::SVESt1Helper(unsigned msize_in_bytes_log2,
5124                              const ZRegister& zt,
5125                              const PRegister& pg,
5126                              const SVEMemOperand& addr) {
5127   if (addr.IsScalarPlusScalar()) {
5128     // Rm must not be xzr.
5129     VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
5130   }
5131 
5132   if (addr.IsScatterGather()) {
5133     bool is_load = false;
5134     bool is_signed = false;
5135     bool is_ff = false;
5136     SVEScatterGatherHelper(msize_in_bytes_log2,
5137                            zt,
5138                            pg,
5139                            addr,
5140                            is_load,
5141                            is_signed,
5142                            is_ff);
5143     return;
5144   }
5145 
5146   Instr op;
5147   if (addr.IsScalarPlusImmediate()) {
5148     op = SVEContiguousStore_ScalarPlusImmFixed;
5149   } else if (addr.IsScalarPlusScalar()) {
5150     op = SVEContiguousStore_ScalarPlusScalarFixed;
5151   } else {
5152     VIXL_UNIMPLEMENTED();
5153     op = 0xffffffff;
5154   }
5155   SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, false, op);
5156 }
5157 
SVESt234Helper(int num_regs,const ZRegister & zt1,const PRegister & pg,const SVEMemOperand & addr)5158 void Assembler::SVESt234Helper(int num_regs,
5159                                const ZRegister& zt1,
5160                                const PRegister& pg,
5161                                const SVEMemOperand& addr) {
5162   if (addr.IsScalarPlusScalar()) {
5163     // Rm must not be xzr.
5164     VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
5165   }
5166 
5167   Instr op;
5168   if (addr.IsScalarPlusImmediate()) {
5169     op = SVEStoreMultipleStructures_ScalarPlusImmFixed;
5170   } else if (addr.IsScalarPlusScalar()) {
5171     op = SVEStoreMultipleStructures_ScalarPlusScalarFixed;
5172   } else {
5173     // These instructions don't support any other addressing modes.
5174     VIXL_ABORT();
5175   }
5176   SVELdSt234Helper(num_regs, zt1, pg, addr, op);
5177 }
5178 
5179 #define VIXL_DEFINE_ST1(MSZ, LANE_SIZE)                           \
5180   void Assembler::st1##MSZ(const ZRegister& zt,                   \
5181                            const PRegister& pg,                   \
5182                            const SVEMemOperand& addr) {           \
5183     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));                       \
5184     SVESt1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr); \
5185   }
5186 #define VIXL_DEFINE_ST2(MSZ, LANE_SIZE)                 \
5187   void Assembler::st2##MSZ(const ZRegister& zt1,        \
5188                            const ZRegister& zt2,        \
5189                            const PRegister& pg,         \
5190                            const SVEMemOperand& addr) { \
5191     USE(zt2);                                           \
5192     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
5193     VIXL_ASSERT(AreConsecutive(zt1, zt2));              \
5194     VIXL_ASSERT(AreSameFormat(zt1, zt2));               \
5195     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
5196     SVESt234Helper(2, zt1, pg, addr);                   \
5197   }
5198 #define VIXL_DEFINE_ST3(MSZ, LANE_SIZE)                 \
5199   void Assembler::st3##MSZ(const ZRegister& zt1,        \
5200                            const ZRegister& zt2,        \
5201                            const ZRegister& zt3,        \
5202                            const PRegister& pg,         \
5203                            const SVEMemOperand& addr) { \
5204     USE(zt2, zt3);                                      \
5205     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
5206     VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3));         \
5207     VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3));          \
5208     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
5209     SVESt234Helper(3, zt1, pg, addr);                   \
5210   }
5211 #define VIXL_DEFINE_ST4(MSZ, LANE_SIZE)                 \
5212   void Assembler::st4##MSZ(const ZRegister& zt1,        \
5213                            const ZRegister& zt2,        \
5214                            const ZRegister& zt3,        \
5215                            const ZRegister& zt4,        \
5216                            const PRegister& pg,         \
5217                            const SVEMemOperand& addr) { \
5218     USE(zt2, zt3, zt4);                                 \
5219     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));             \
5220     VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4));    \
5221     VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4));     \
5222     VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE());           \
5223     SVESt234Helper(4, zt1, pg, addr);                   \
5224   }
5225 
5226 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST1)
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST2)5227 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST2)
5228 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST3)
5229 VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST4)
5230 
5231 void Assembler::stnt1b(const ZRegister& zt,
5232                        const PRegister& pg,
5233                        const SVEMemOperand& addr) {
5234   VIXL_ASSERT(addr.IsPlainScalar() ||
5235               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5236               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||
5237               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5238   if (addr.IsVectorPlusScalar()) {
5239     SVESt1VecScaHelper(zt, pg, addr, 0);
5240   } else {
5241     SVELd1St1ScaImmHelper(zt,
5242                           pg,
5243                           addr,
5244                           STNT1B_z_p_br_contiguous,
5245                           STNT1B_z_p_bi_contiguous);
5246   }
5247 }
5248 
stnt1d(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr)5249 void Assembler::stnt1d(const ZRegister& zt,
5250                        const PRegister& pg,
5251                        const SVEMemOperand& addr) {
5252   VIXL_ASSERT(addr.IsPlainScalar() ||
5253               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5254               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||
5255               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5256   if (addr.IsVectorPlusScalar()) {
5257     SVESt1VecScaHelper(zt, pg, addr, 3);
5258   } else {
5259     SVELd1St1ScaImmHelper(zt,
5260                           pg,
5261                           addr,
5262                           STNT1D_z_p_br_contiguous,
5263                           STNT1D_z_p_bi_contiguous);
5264   }
5265 }
5266 
stnt1h(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr)5267 void Assembler::stnt1h(const ZRegister& zt,
5268                        const PRegister& pg,
5269                        const SVEMemOperand& addr) {
5270   VIXL_ASSERT(addr.IsPlainScalar() ||
5271               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5272               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||
5273               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5274   if (addr.IsVectorPlusScalar()) {
5275     SVESt1VecScaHelper(zt, pg, addr, 1);
5276   } else {
5277     SVELd1St1ScaImmHelper(zt,
5278                           pg,
5279                           addr,
5280                           STNT1H_z_p_br_contiguous,
5281                           STNT1H_z_p_bi_contiguous);
5282   }
5283 }
5284 
stnt1w(const ZRegister & zt,const PRegister & pg,const SVEMemOperand & addr)5285 void Assembler::stnt1w(const ZRegister& zt,
5286                        const PRegister& pg,
5287                        const SVEMemOperand& addr) {
5288   VIXL_ASSERT(addr.IsPlainScalar() ||
5289               (addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5290               (addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||
5291               (addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5292   if (addr.IsVectorPlusScalar()) {
5293     SVESt1VecScaHelper(zt, pg, addr, 2);
5294   } else {
5295     SVELd1St1ScaImmHelper(zt,
5296                           pg,
5297                           addr,
5298                           STNT1W_z_p_br_contiguous,
5299                           STNT1W_z_p_bi_contiguous);
5300   }
5301 }
5302 
str(const CPURegister & rt,const SVEMemOperand & addr)5303 void Assembler::str(const CPURegister& rt, const SVEMemOperand& addr) {
5304   // STR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]
5305 
5306   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5307   VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());
5308   VIXL_ASSERT(addr.IsPlainScalar() ||
5309               (addr.IsScalarPlusImmediate() &&
5310                (addr.GetOffsetModifier() == SVE_MUL_VL)));
5311   int64_t imm9 = addr.GetImmediateOffset();
5312   VIXL_ASSERT(IsInt9(imm9));
5313   Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;
5314   Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;
5315 
5316   Instr op = STR_z_bi;
5317   if (rt.IsPRegister()) {
5318     op = STR_p_bi;
5319   }
5320   Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);
5321 }
5322 
5323 // SVEMulIndex.
5324 
sdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)5325 void Assembler::sdot(const ZRegister& zda,
5326                      const ZRegister& zn,
5327                      const ZRegister& zm,
5328                      int index) {
5329   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5330   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
5331   VIXL_ASSERT(AreSameLaneSize(zn, zm));
5332 
5333   Instr op = 0xffffffff;
5334   switch (zda.GetLaneSizeInBits()) {
5335     case kSRegSize:
5336       VIXL_ASSERT(IsUint2(index));
5337       op = SDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);
5338       break;
5339     case kDRegSize:
5340       VIXL_ASSERT(IsUint1(index));
5341       op = SDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);
5342       break;
5343     default:
5344       VIXL_UNIMPLEMENTED();
5345       break;
5346   }
5347 
5348   Emit(op);
5349 }
5350 
udot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)5351 void Assembler::udot(const ZRegister& zda,
5352                      const ZRegister& zn,
5353                      const ZRegister& zm,
5354                      int index) {
5355   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5356   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
5357   VIXL_ASSERT(AreSameLaneSize(zn, zm));
5358 
5359   Instr op = 0xffffffff;
5360   switch (zda.GetLaneSizeInBits()) {
5361     case kSRegSize:
5362       VIXL_ASSERT(IsUint2(index));
5363       op = UDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);
5364       break;
5365     case kDRegSize:
5366       VIXL_ASSERT(IsUint1(index));
5367       op = UDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);
5368       break;
5369     default:
5370       VIXL_UNIMPLEMENTED();
5371       break;
5372   }
5373 
5374   Emit(op);
5375 }
5376 
5377 // SVEPartitionBreak.
5378 
brka(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)5379 void Assembler::brka(const PRegisterWithLaneSize& pd,
5380                      const PRegister& pg,
5381                      const PRegisterWithLaneSize& pn) {
5382   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5383   VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
5384   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5385 
5386   Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;
5387   Emit(BRKA_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));
5388 }
5389 
brkas(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5390 void Assembler::brkas(const PRegisterWithLaneSize& pd,
5391                       const PRegisterZ& pg,
5392                       const PRegisterWithLaneSize& pn) {
5393   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5394   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5395 
5396   Emit(BRKAS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5397 }
5398 
brkb(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)5399 void Assembler::brkb(const PRegisterWithLaneSize& pd,
5400                      const PRegister& pg,
5401                      const PRegisterWithLaneSize& pn) {
5402   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5403   VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
5404   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5405 
5406   Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;
5407   Emit(BRKB_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));
5408 }
5409 
brkbs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5410 void Assembler::brkbs(const PRegisterWithLaneSize& pd,
5411                       const PRegisterZ& pg,
5412                       const PRegisterWithLaneSize& pn) {
5413   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5414   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5415 
5416   Emit(BRKBS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5417 }
5418 
brkn(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5419 void Assembler::brkn(const PRegisterWithLaneSize& pd,
5420                      const PRegisterZ& pg,
5421                      const PRegisterWithLaneSize& pn,
5422                      const PRegisterWithLaneSize& pm) {
5423   USE(pm);
5424   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5425   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5426   VIXL_ASSERT(pd.Is(pm));
5427 
5428   Emit(BRKN_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5429 }
5430 
brkns(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5431 void Assembler::brkns(const PRegisterWithLaneSize& pd,
5432                       const PRegisterZ& pg,
5433                       const PRegisterWithLaneSize& pn,
5434                       const PRegisterWithLaneSize& pm) {
5435   USE(pm);
5436   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5437   VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5438   VIXL_ASSERT(pd.Is(pm));
5439 
5440   Emit(BRKNS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5441 }
5442 
5443 // SVEPermutePredicate.
5444 
punpkhi(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5445 void Assembler::punpkhi(const PRegisterWithLaneSize& pd,
5446                         const PRegisterWithLaneSize& pn) {
5447   // PUNPKHI <Pd>.H, <Pn>.B
5448   //  0000 0101 0011 0001 0100 000. ...0 ....
5449   //  H<16> = 1 | Pn<8:5> | Pd<3:0>
5450 
5451   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5452   VIXL_ASSERT(pd.IsLaneSizeH());
5453   VIXL_ASSERT(pn.IsLaneSizeB());
5454 
5455   Emit(PUNPKHI_p_p | Pd(pd) | Pn(pn));
5456 }
5457 
punpklo(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5458 void Assembler::punpklo(const PRegisterWithLaneSize& pd,
5459                         const PRegisterWithLaneSize& pn) {
5460   // PUNPKLO <Pd>.H, <Pn>.B
5461   //  0000 0101 0011 0000 0100 000. ...0 ....
5462   //  H<16> = 0 | Pn<8:5> | Pd<3:0>
5463 
5464   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5465   VIXL_ASSERT(pd.IsLaneSizeH());
5466   VIXL_ASSERT(pn.IsLaneSizeB());
5467 
5468   Emit(PUNPKLO_p_p | Pd(pd) | Pn(pn));
5469 }
5470 
rev(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5471 void Assembler::rev(const PRegisterWithLaneSize& pd,
5472                     const PRegisterWithLaneSize& pn) {
5473   // REV <Pd>.<T>, <Pn>.<T>
5474   //  0000 0101 ..11 0100 0100 000. ...0 ....
5475   //  size<23:22> | Pn<8:5> | Pd<3:0>
5476 
5477   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5478   VIXL_ASSERT(AreSameLaneSize(pd, pn));
5479 
5480   Emit(REV_p_p | SVESize(pd) | Pd(pd) | Rx<8, 5>(pn));
5481 }
5482 
trn1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5483 void Assembler::trn1(const PRegisterWithLaneSize& pd,
5484                      const PRegisterWithLaneSize& pn,
5485                      const PRegisterWithLaneSize& pm) {
5486   // TRN1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5487   //  0000 0101 ..10 .... 0101 000. ...0 ....
5488   //  size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5489 
5490   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5491   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5492 
5493   Emit(TRN1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5494 }
5495 
trn2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5496 void Assembler::trn2(const PRegisterWithLaneSize& pd,
5497                      const PRegisterWithLaneSize& pn,
5498                      const PRegisterWithLaneSize& pm) {
5499   // TRN2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5500   //  0000 0101 ..10 .... 0101 010. ...0 ....
5501   //  size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5502 
5503   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5504   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5505 
5506   Emit(TRN2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5507 }
5508 
uzp1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5509 void Assembler::uzp1(const PRegisterWithLaneSize& pd,
5510                      const PRegisterWithLaneSize& pn,
5511                      const PRegisterWithLaneSize& pm) {
5512   // UZP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5513   //  0000 0101 ..10 .... 0100 100. ...0 ....
5514   //  size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5515 
5516   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5517   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5518 
5519   Emit(UZP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5520 }
5521 
uzp2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5522 void Assembler::uzp2(const PRegisterWithLaneSize& pd,
5523                      const PRegisterWithLaneSize& pn,
5524                      const PRegisterWithLaneSize& pm) {
5525   // UZP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5526   //  0000 0101 ..10 .... 0100 110. ...0 ....
5527   //  size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5528 
5529   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5530   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5531 
5532   Emit(UZP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5533 }
5534 
zip1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5535 void Assembler::zip1(const PRegisterWithLaneSize& pd,
5536                      const PRegisterWithLaneSize& pn,
5537                      const PRegisterWithLaneSize& pm) {
5538   // ZIP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5539   //  0000 0101 ..10 .... 0100 000. ...0 ....
5540   //  size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5541 
5542   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5543   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5544 
5545   Emit(ZIP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5546 }
5547 
zip2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5548 void Assembler::zip2(const PRegisterWithLaneSize& pd,
5549                      const PRegisterWithLaneSize& pn,
5550                      const PRegisterWithLaneSize& pm) {
5551   // ZIP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5552   //  0000 0101 ..10 .... 0100 010. ...0 ....
5553   //  size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5554 
5555   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5556   VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5557 
5558   Emit(ZIP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5559 }
5560 
5561 // SVEPermuteVectorExtract.
5562 
ext(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,unsigned offset)5563 void Assembler::ext(const ZRegister& zd,
5564                     const ZRegister& zn,
5565                     const ZRegister& zm,
5566                     unsigned offset) {
5567   // EXT <Zdn>.B, <Zdn>.B, <Zm>.B, #<imm>
5568   //  0000 0101 001. .... 000. .... .... ....
5569   //  imm8h<20:16> | imm8l<12:10> | Zm<9:5> | Zdn<4:0>
5570 
5571   // EXT <Zd>.B, { <Zn1>.B, <Zn2>.B }, #<imm>
5572   //  0000 0101 011. .... 000. .... .... ....
5573   //  imm8h<20:16> | imm8l<12:10> | Zn<9:5> | Zd<4:0>
5574 
5575   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5576   VIXL_ASSERT(IsUint8(offset));
5577 
5578   int imm8h = ExtractUnsignedBitfield32(7, 3, offset);
5579   int imm8l = ExtractUnsignedBitfield32(2, 0, offset);
5580 
5581   Instr op;
5582   if (zd.Is(zn)) {
5583     // Destructive form.
5584     op = EXT_z_zi_des | Rn(zm);
5585   } else {
5586     // Constructive form (requires SVE2).
5587     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2) && AreConsecutive(zn, zm));
5588     op = 0x05600000 | Rn(zn);
5589   }
5590 
5591   Emit(op | Rd(zd) | ImmUnsignedField<20, 16>(imm8h) |
5592        ImmUnsignedField<12, 10>(imm8l));
5593 }
5594 
5595 // SVEPermuteVectorInterleaving.
5596 
trn1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5597 void Assembler::trn1(const ZRegister& zd,
5598                      const ZRegister& zn,
5599                      const ZRegister& zm) {
5600   // TRN1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5601   //  0000 0101 ..1. .... 0111 00.. .... ....
5602   //  size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>
5603 
5604   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5605   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5606 
5607   Emit(TRN1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5608 }
5609 
trn2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5610 void Assembler::trn2(const ZRegister& zd,
5611                      const ZRegister& zn,
5612                      const ZRegister& zm) {
5613   // TRN2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5614   //  0000 0101 ..1. .... 0111 01.. .... ....
5615   //  size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>
5616 
5617   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5618   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5619 
5620   Emit(TRN2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5621 }
5622 
uzp1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5623 void Assembler::uzp1(const ZRegister& zd,
5624                      const ZRegister& zn,
5625                      const ZRegister& zm) {
5626   // UZP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5627   //  0000 0101 ..1. .... 0110 10.. .... ....
5628   //  size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>
5629 
5630   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5631   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5632 
5633   Emit(UZP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5634 }
5635 
uzp2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5636 void Assembler::uzp2(const ZRegister& zd,
5637                      const ZRegister& zn,
5638                      const ZRegister& zm) {
5639   // UZP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5640   //  0000 0101 ..1. .... 0110 11.. .... ....
5641   //  size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>
5642 
5643   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5644   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5645 
5646   Emit(UZP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5647 }
5648 
zip1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5649 void Assembler::zip1(const ZRegister& zd,
5650                      const ZRegister& zn,
5651                      const ZRegister& zm) {
5652   // ZIP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5653   //  0000 0101 ..1. .... 0110 00.. .... ....
5654   //  size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
5655 
5656   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5657   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5658 
5659   Emit(ZIP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5660 }
5661 
zip2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5662 void Assembler::zip2(const ZRegister& zd,
5663                      const ZRegister& zn,
5664                      const ZRegister& zm) {
5665   // ZIP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5666   //  0000 0101 ..1. .... 0110 01.. .... ....
5667   //  size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
5668 
5669   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5670   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5671 
5672   Emit(ZIP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5673 }
5674 
5675 // SVEPermuteVectorPredicated.
5676 
clasta(const Register & rd,const PRegister & pg,const Register & rn,const ZRegister & zm)5677 void Assembler::clasta(const Register& rd,
5678                        const PRegister& pg,
5679                        const Register& rn,
5680                        const ZRegister& zm) {
5681   // CLASTA <R><dn>, <Pg>, <R><dn>, <Zm>.<T>
5682   //  0000 0101 ..11 0000 101. .... .... ....
5683   //  size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Rdn<4:0>
5684 
5685   USE(rn);
5686   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5687   VIXL_ASSERT(rd.Is(rn));
5688 
5689   Emit(CLASTA_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));
5690 }
5691 
clasta(const VRegister & vd,const PRegister & pg,const VRegister & vn,const ZRegister & zm)5692 void Assembler::clasta(const VRegister& vd,
5693                        const PRegister& pg,
5694                        const VRegister& vn,
5695                        const ZRegister& zm) {
5696   // CLASTA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
5697   //  0000 0101 ..10 1010 100. .... .... ....
5698   //  size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
5699 
5700   USE(vn);
5701   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5702   VIXL_ASSERT(vd.Is(vn));
5703   VIXL_ASSERT(vd.IsScalar());
5704   VIXL_ASSERT(AreSameLaneSize(vd, zm));
5705 
5706   Emit(CLASTA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
5707 }
5708 
clasta(const ZRegister & zd,const PRegister & pg,const ZRegister & zn,const ZRegister & zm)5709 void Assembler::clasta(const ZRegister& zd,
5710                        const PRegister& pg,
5711                        const ZRegister& zn,
5712                        const ZRegister& zm) {
5713   // CLASTA <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5714   //  0000 0101 ..10 1000 100. .... .... ....
5715   //  size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5716 
5717   USE(zn);
5718   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5719   VIXL_ASSERT(zd.Is(zn));
5720   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5721 
5722   Emit(CLASTA_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5723 }
5724 
clastb(const Register & rd,const PRegister & pg,const Register & rn,const ZRegister & zm)5725 void Assembler::clastb(const Register& rd,
5726                        const PRegister& pg,
5727                        const Register& rn,
5728                        const ZRegister& zm) {
5729   // CLASTB <R><dn>, <Pg>, <R><dn>, <Zm>.<T>
5730   //  0000 0101 ..11 0001 101. .... .... ....
5731   //  size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Rdn<4:0>
5732 
5733   USE(rn);
5734   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5735   VIXL_ASSERT(rd.Is(rn));
5736 
5737   Emit(CLASTB_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));
5738 }
5739 
clastb(const VRegister & vd,const PRegister & pg,const VRegister & vn,const ZRegister & zm)5740 void Assembler::clastb(const VRegister& vd,
5741                        const PRegister& pg,
5742                        const VRegister& vn,
5743                        const ZRegister& zm) {
5744   // CLASTB <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
5745   //  0000 0101 ..10 1011 100. .... .... ....
5746   //  size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
5747 
5748   USE(vn);
5749   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5750   VIXL_ASSERT(vd.Is(vn));
5751   VIXL_ASSERT(vd.IsScalar());
5752   VIXL_ASSERT(AreSameLaneSize(vd, zm));
5753 
5754   Emit(CLASTB_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
5755 }
5756 
clastb(const ZRegister & zd,const PRegister & pg,const ZRegister & zn,const ZRegister & zm)5757 void Assembler::clastb(const ZRegister& zd,
5758                        const PRegister& pg,
5759                        const ZRegister& zn,
5760                        const ZRegister& zm) {
5761   // CLASTB <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5762   //  0000 0101 ..10 1001 100. .... .... ....
5763   //  size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5764 
5765   USE(zn);
5766   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5767   VIXL_ASSERT(zd.Is(zn));
5768   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5769 
5770   Emit(CLASTB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5771 }
5772 
compact(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)5773 void Assembler::compact(const ZRegister& zd,
5774                         const PRegister& pg,
5775                         const ZRegister& zn) {
5776   // COMPACT <Zd>.<T>, <Pg>, <Zn>.<T>
5777   //  0000 0101 1.10 0001 100. .... .... ....
5778   //  sz<22> | Pg<12:10> | Zn<9:5> | Zd<4:0>
5779 
5780   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5781   VIXL_ASSERT(AreSameLaneSize(zd, zn));
5782   VIXL_ASSERT((zd.GetLaneSizeInBits() == kSRegSize) ||
5783               (zd.GetLaneSizeInBits() == kDRegSize));
5784 
5785   Instr sz = (zd.GetLaneSizeInBits() == kDRegSize) ? (1 << 22) : 0;
5786   Emit(COMPACT_z_p_z | sz | Rd(zd) | PgLow8(pg) | Rn(zn));
5787 }
5788 
cpy(const ZRegister & zd,const PRegisterM & pg,const Register & rn)5789 void Assembler::cpy(const ZRegister& zd,
5790                     const PRegisterM& pg,
5791                     const Register& rn) {
5792   // CPY <Zd>.<T>, <Pg>/M, <R><n|SP>
5793   //  0000 0101 ..10 1000 101. .... .... ....
5794   //  size<23:22> | Pg<12:10> | Rn<9:5> | Zd<4:0>
5795 
5796   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5797   VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
5798               zd.GetLaneSizeInBits());
5799 
5800   Emit(CPY_z_p_r | SVESize(zd) | Rd(zd) | PgLow8(pg) | RnSP(rn));
5801 }
5802 
cpy(const ZRegister & zd,const PRegisterM & pg,const VRegister & vn)5803 void Assembler::cpy(const ZRegister& zd,
5804                     const PRegisterM& pg,
5805                     const VRegister& vn) {
5806   // CPY <Zd>.<T>, <Pg>/M, <V><n>
5807   //  0000 0101 ..10 0000 100. .... .... ....
5808   //  size<23:22> | Pg<12:10> | Vn<9:5> | Zd<4:0>
5809 
5810   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5811   VIXL_ASSERT(vn.IsScalar());
5812   VIXL_ASSERT(static_cast<unsigned>(vn.GetSizeInBits()) ==
5813               zd.GetLaneSizeInBits());
5814 
5815   Emit(CPY_z_p_v | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(vn));
5816 }
5817 
lasta(const Register & rd,const PRegister & pg,const ZRegister & zn)5818 void Assembler::lasta(const Register& rd,
5819                       const PRegister& pg,
5820                       const ZRegister& zn) {
5821   // LASTA <R><d>, <Pg>, <Zn>.<T>
5822   //  0000 0101 ..10 0000 101. .... .... ....
5823   //  size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Rd<4:0>
5824 
5825   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5826 
5827   Emit(LASTA_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));
5828 }
5829 
lasta(const VRegister & vd,const PRegister & pg,const ZRegister & zn)5830 void Assembler::lasta(const VRegister& vd,
5831                       const PRegister& pg,
5832                       const ZRegister& zn) {
5833   // LASTA <V><d>, <Pg>, <Zn>.<T>
5834   //  0000 0101 ..10 0010 100. .... .... ....
5835   //  size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Vd<4:0>
5836 
5837   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5838   VIXL_ASSERT(vd.IsScalar());
5839 
5840   Emit(LASTA_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
5841 }
5842 
lastb(const Register & rd,const PRegister & pg,const ZRegister & zn)5843 void Assembler::lastb(const Register& rd,
5844                       const PRegister& pg,
5845                       const ZRegister& zn) {
5846   // LASTB <R><d>, <Pg>, <Zn>.<T>
5847   //  0000 0101 ..10 0001 101. .... .... ....
5848   //  size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Rd<4:0>
5849 
5850   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5851 
5852   Emit(LASTB_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));
5853 }
5854 
lastb(const VRegister & vd,const PRegister & pg,const ZRegister & zn)5855 void Assembler::lastb(const VRegister& vd,
5856                       const PRegister& pg,
5857                       const ZRegister& zn) {
5858   // LASTB <V><d>, <Pg>, <Zn>.<T>
5859   //  0000 0101 ..10 0011 100. .... .... ....
5860   //  size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Vd<4:0>
5861 
5862   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5863   VIXL_ASSERT(vd.IsScalar());
5864 
5865   Emit(LASTB_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
5866 }
5867 
rbit(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5868 void Assembler::rbit(const ZRegister& zd,
5869                      const PRegisterM& pg,
5870                      const ZRegister& zn) {
5871   // RBIT <Zd>.<T>, <Pg>/M, <Zn>.<T>
5872   //  0000 0101 ..10 0111 100. .... .... ....
5873   //  size<23:22> | opc<17:16> = 11 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5874 
5875   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5876   VIXL_ASSERT(AreSameLaneSize(zd, zn));
5877 
5878   Emit(RBIT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5879 }
5880 
revb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5881 void Assembler::revb(const ZRegister& zd,
5882                      const PRegisterM& pg,
5883                      const ZRegister& zn) {
5884   // REVB <Zd>.<T>, <Pg>/M, <Zn>.<T>
5885   //  0000 0101 ..10 0100 100. .... .... ....
5886   //  size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5887 
5888   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5889   VIXL_ASSERT(AreSameLaneSize(zd, zn));
5890   VIXL_ASSERT(zd.IsLaneSizeH() || zd.IsLaneSizeS() || zd.IsLaneSizeD());
5891 
5892   Emit(REVB_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5893 }
5894 
revh(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5895 void Assembler::revh(const ZRegister& zd,
5896                      const PRegisterM& pg,
5897                      const ZRegister& zn) {
5898   // REVH <Zd>.<T>, <Pg>/M, <Zn>.<T>
5899   //  0000 0101 ..10 0101 100. .... .... ....
5900   //  size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5901 
5902   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5903   VIXL_ASSERT(AreSameLaneSize(zd, zn));
5904   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
5905 
5906   Emit(REVH_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5907 }
5908 
revw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5909 void Assembler::revw(const ZRegister& zd,
5910                      const PRegisterM& pg,
5911                      const ZRegister& zn) {
5912   // REVW <Zd>.D, <Pg>/M, <Zn>.D
5913   //  0000 0101 ..10 0110 100. .... .... ....
5914   //  size<23:22> | opc<17:16> = 10 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5915 
5916   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5917   VIXL_ASSERT(AreSameLaneSize(zd, zn));
5918   VIXL_ASSERT(zd.IsLaneSizeD());
5919 
5920   Emit(REVW_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5921 }
5922 
splice(const ZRegister & zd,const PRegister & pg,const ZRegister & zn,const ZRegister & zm)5923 void Assembler::splice(const ZRegister& zd,
5924                        const PRegister& pg,
5925                        const ZRegister& zn,
5926                        const ZRegister& zm) {
5927   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5928 
5929   if (zd.Aliases(zn)) {
5930     // SPLICE <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5931     //  0000 0101 ..10 1100 100. .... .... ....
5932     //  size<23:22> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5933 
5934     USE(zn);
5935     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5936     VIXL_ASSERT(zd.Is(zn));
5937 
5938     Emit(SPLICE_z_p_zz_des | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5939   } else {
5940     splice_con(zd, pg, zn, zm);
5941   }
5942 }
5943 
splice_con(const ZRegister & zd,const PRegister & pg,const ZRegister & zn1,const ZRegister & zn2)5944 void Assembler::splice_con(const ZRegister& zd,
5945                            const PRegister& pg,
5946                            const ZRegister& zn1,
5947                            const ZRegister& zn2) {
5948   // SPLICE <Zd>.<T>, <Pg>, { <Zn1>.<T>, <Zn2>.<T> }
5949   //  0000 0101 ..10 1101 100. .... .... ....
5950   //  size<23:22> | Pg<12:10> | Zn<9:5> | Zd<4:0>
5951 
5952   USE(zn2);
5953   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
5954   VIXL_ASSERT(AreConsecutive(zn1, zn2));
5955   VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2));
5956 
5957   Emit(0x052d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn1));
5958 }
5959 
5960 // SVEPermuteVectorUnpredicated.
5961 
dup(const ZRegister & zd,const Register & xn)5962 void Assembler::dup(const ZRegister& zd, const Register& xn) {
5963   // DUP <Zd>.<T>, <R><n|SP>
5964   //  0000 0101 ..10 0000 0011 10.. .... ....
5965   //  size<23:22> | Rn<9:5> | Zd<4:0>
5966 
5967   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5968 
5969   Emit(DUP_z_r | SVESize(zd) | Rd(zd) | RnSP(xn));
5970 }
5971 
dup(const ZRegister & zd,const ZRegister & zn,unsigned index)5972 void Assembler::dup(const ZRegister& zd, const ZRegister& zn, unsigned index) {
5973   // DUP <Zd>.<T>, <Zn>.<T>[<imm>]
5974   //  0000 0101 ..1. .... 0010 00.. .... ....
5975   //  imm2<23:22> | tsz<20:16> | Zn<9:5> | Zd<4:0>
5976 
5977   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5978   VIXL_ASSERT(AreSameFormat(zd, zn));
5979   VIXL_ASSERT((index * zd.GetLaneSizeInBits()) < 512);
5980   int n = zd.GetLaneSizeInBytesLog2();
5981   unsigned imm_7 = (index << (n + 1)) | (1 << n);
5982   VIXL_ASSERT(IsUint7(imm_7));
5983   unsigned imm_2 = ExtractUnsignedBitfield32(6, 5, imm_7);
5984   unsigned tsz_5 = ExtractUnsignedBitfield32(4, 0, imm_7);
5985 
5986   Emit(DUP_z_zi | ImmUnsignedField<23, 22>(imm_2) |
5987        ImmUnsignedField<20, 16>(tsz_5) | Rd(zd) | Rn(zn));
5988 }
5989 
insr(const ZRegister & zdn,const Register & rm)5990 void Assembler::insr(const ZRegister& zdn, const Register& rm) {
5991   // INSR <Zdn>.<T>, <R><m>
5992   //  0000 0101 ..10 0100 0011 10.. .... ....
5993   //  size<23:22> | Rm<9:5> | Zdn<4:0>
5994 
5995   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5996 
5997   Emit(INSR_z_r | SVESize(zdn) | Rd(zdn) | Rn(rm));
5998 }
5999 
insr(const ZRegister & zdn,const VRegister & vm)6000 void Assembler::insr(const ZRegister& zdn, const VRegister& vm) {
6001   // INSR <Zdn>.<T>, <V><m>
6002   //  0000 0101 ..11 0100 0011 10.. .... ....
6003   //  size<23:22> | Vm<9:5> | Zdn<4:0>
6004 
6005   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6006   VIXL_ASSERT(vm.IsScalar());
6007 
6008   Emit(INSR_z_v | SVESize(zdn) | Rd(zdn) | Rn(vm));
6009 }
6010 
rev(const ZRegister & zd,const ZRegister & zn)6011 void Assembler::rev(const ZRegister& zd, const ZRegister& zn) {
6012   // REV <Zd>.<T>, <Zn>.<T>
6013   //  0000 0101 ..11 1000 0011 10.. .... ....
6014   //  size<23:22> | Zn<9:5> | Zd<4:0>
6015 
6016   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6017   VIXL_ASSERT(AreSameFormat(zd, zn));
6018 
6019   Emit(REV_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6020 }
6021 
sunpkhi(const ZRegister & zd,const ZRegister & zn)6022 void Assembler::sunpkhi(const ZRegister& zd, const ZRegister& zn) {
6023   // SUNPKHI <Zd>.<T>, <Zn>.<Tb>
6024   //  0000 0101 ..11 0001 0011 10.. .... ....
6025   //  size<23:22> | U<17> = 0 | H<16> = 1 | Zn<9:5> | Zd<4:0>
6026 
6027   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6028   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6029   VIXL_ASSERT(!zd.IsLaneSizeB());
6030 
6031   Emit(SUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6032 }
6033 
sunpklo(const ZRegister & zd,const ZRegister & zn)6034 void Assembler::sunpklo(const ZRegister& zd, const ZRegister& zn) {
6035   // SUNPKLO <Zd>.<T>, <Zn>.<Tb>
6036   //  0000 0101 ..11 0000 0011 10.. .... ....
6037   //  size<23:22> | U<17> = 0 | H<16> = 0 | Zn<9:5> | Zd<4:0>
6038 
6039   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6040   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6041   VIXL_ASSERT(!zd.IsLaneSizeB());
6042 
6043   Emit(SUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6044 }
6045 
tbl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6046 void Assembler::tbl(const ZRegister& zd,
6047                     const ZRegister& zn,
6048                     const ZRegister& zm) {
6049   // TBL <Zd>.<T>, { <Zn>.<T> }, <Zm>.<T>
6050   //  0000 0101 ..1. .... 0011 00.. .... ....
6051   //  size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>
6052 
6053   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6054   VIXL_ASSERT(AreSameFormat(zd, zn, zm));
6055 
6056   Emit(TBL_z_zz_1 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6057 }
6058 
uunpkhi(const ZRegister & zd,const ZRegister & zn)6059 void Assembler::uunpkhi(const ZRegister& zd, const ZRegister& zn) {
6060   // UUNPKHI <Zd>.<T>, <Zn>.<Tb>
6061   //  0000 0101 ..11 0011 0011 10.. .... ....
6062   //  size<23:22> | U<17> = 1 | H<16> = 1 | Zn<9:5> | Zd<4:0>
6063 
6064   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6065   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6066   VIXL_ASSERT(!zd.IsLaneSizeB());
6067 
6068   Emit(UUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6069 }
6070 
uunpklo(const ZRegister & zd,const ZRegister & zn)6071 void Assembler::uunpklo(const ZRegister& zd, const ZRegister& zn) {
6072   // UUNPKLO <Zd>.<T>, <Zn>.<Tb>
6073   //  0000 0101 ..11 0010 0011 10.. .... ....
6074   //  size<23:22> | U<17> = 1 | H<16> = 0 | Zn<9:5> | Zd<4:0>
6075 
6076   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6077   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6078   VIXL_ASSERT(!zd.IsLaneSizeB());
6079 
6080   Emit(UUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6081 }
6082 
6083 // SVEPredicateCount.
6084 
cntp(const Register & xd,const PRegister & pg,const PRegisterWithLaneSize & pn)6085 void Assembler::cntp(const Register& xd,
6086                      const PRegister& pg,
6087                      const PRegisterWithLaneSize& pn) {
6088   // CNTP <Xd>, <Pg>, <Pn>.<T>
6089   //  0010 0101 ..10 0000 10.. ..0. .... ....
6090   //  size<23:22> | opc<18:16> = 000 | Pg<13:10> | o2<9> = 0 | Pn<8:5> | Rd<4:0>
6091 
6092   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6093   VIXL_ASSERT(xd.IsX());
6094   VIXL_ASSERT(pg.IsUnqualified());
6095   if (pg.HasLaneSize()) VIXL_ASSERT(AreSameFormat(pg, pn));
6096 
6097   Emit(CNTP_r_p_p | SVESize(pn) | Rd(xd) | Pg<13, 10>(pg) | Pn(pn));
6098 }
6099 
6100 // SVEPredicateLogicalOp.
and_(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6101 void Assembler::and_(const PRegisterWithLaneSize& pd,
6102                      const PRegisterZ& pg,
6103                      const PRegisterWithLaneSize& pn,
6104                      const PRegisterWithLaneSize& pm) {
6105   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6106   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6107   VIXL_ASSERT(pd.IsLaneSizeB());
6108   Emit(AND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6109 }
6110 
ands(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6111 void Assembler::ands(const PRegisterWithLaneSize& pd,
6112                      const PRegisterZ& pg,
6113                      const PRegisterWithLaneSize& pn,
6114                      const PRegisterWithLaneSize& pm) {
6115   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6116   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6117   VIXL_ASSERT(pd.IsLaneSizeB());
6118   Emit(ANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6119 }
6120 
bic(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6121 void Assembler::bic(const PRegisterWithLaneSize& pd,
6122                     const PRegisterZ& pg,
6123                     const PRegisterWithLaneSize& pn,
6124                     const PRegisterWithLaneSize& pm) {
6125   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6126   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6127   VIXL_ASSERT(pd.IsLaneSizeB());
6128   Emit(BIC_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6129 }
6130 
bics(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6131 void Assembler::bics(const PRegisterWithLaneSize& pd,
6132                      const PRegisterZ& pg,
6133                      const PRegisterWithLaneSize& pn,
6134                      const PRegisterWithLaneSize& pm) {
6135   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6136   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6137   VIXL_ASSERT(pd.IsLaneSizeB());
6138   Emit(BICS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6139 }
6140 
eor(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6141 void Assembler::eor(const PRegisterWithLaneSize& pd,
6142                     const PRegisterZ& pg,
6143                     const PRegisterWithLaneSize& pn,
6144                     const PRegisterWithLaneSize& pm) {
6145   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6146   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6147   VIXL_ASSERT(pd.IsLaneSizeB());
6148   Emit(EOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6149 }
6150 
eors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6151 void Assembler::eors(const PRegisterWithLaneSize& pd,
6152                      const PRegisterZ& pg,
6153                      const PRegisterWithLaneSize& pn,
6154                      const PRegisterWithLaneSize& pm) {
6155   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6156   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6157   VIXL_ASSERT(pd.IsLaneSizeB());
6158   Emit(EORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6159 }
6160 
nand(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6161 void Assembler::nand(const PRegisterWithLaneSize& pd,
6162                      const PRegisterZ& pg,
6163                      const PRegisterWithLaneSize& pn,
6164                      const PRegisterWithLaneSize& pm) {
6165   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6166   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6167   VIXL_ASSERT(pd.IsLaneSizeB());
6168   Emit(NAND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6169 }
6170 
nands(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6171 void Assembler::nands(const PRegisterWithLaneSize& pd,
6172                       const PRegisterZ& pg,
6173                       const PRegisterWithLaneSize& pn,
6174                       const PRegisterWithLaneSize& pm) {
6175   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6176   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6177   VIXL_ASSERT(pd.IsLaneSizeB());
6178   Emit(NANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6179 }
6180 
nor(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6181 void Assembler::nor(const PRegisterWithLaneSize& pd,
6182                     const PRegisterZ& pg,
6183                     const PRegisterWithLaneSize& pn,
6184                     const PRegisterWithLaneSize& pm) {
6185   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6186   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6187   VIXL_ASSERT(pd.IsLaneSizeB());
6188   Emit(NOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6189 }
6190 
nors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6191 void Assembler::nors(const PRegisterWithLaneSize& pd,
6192                      const PRegisterZ& pg,
6193                      const PRegisterWithLaneSize& pn,
6194                      const PRegisterWithLaneSize& pm) {
6195   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6196   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6197   VIXL_ASSERT(pd.IsLaneSizeB());
6198   Emit(NORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6199 }
6200 
orn(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6201 void Assembler::orn(const PRegisterWithLaneSize& pd,
6202                     const PRegisterZ& pg,
6203                     const PRegisterWithLaneSize& pn,
6204                     const PRegisterWithLaneSize& pm) {
6205   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6206   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6207   VIXL_ASSERT(pd.IsLaneSizeB());
6208   Emit(ORN_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6209 }
6210 
orns(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6211 void Assembler::orns(const PRegisterWithLaneSize& pd,
6212                      const PRegisterZ& pg,
6213                      const PRegisterWithLaneSize& pn,
6214                      const PRegisterWithLaneSize& pm) {
6215   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6216   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6217   VIXL_ASSERT(pd.IsLaneSizeB());
6218   Emit(ORNS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6219 }
6220 
orr(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6221 void Assembler::orr(const PRegisterWithLaneSize& pd,
6222                     const PRegisterZ& pg,
6223                     const PRegisterWithLaneSize& pn,
6224                     const PRegisterWithLaneSize& pm) {
6225   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6226   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6227   VIXL_ASSERT(pd.IsLaneSizeB());
6228   Emit(ORR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6229 }
6230 
orrs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6231 void Assembler::orrs(const PRegisterWithLaneSize& pd,
6232                      const PRegisterZ& pg,
6233                      const PRegisterWithLaneSize& pn,
6234                      const PRegisterWithLaneSize& pm) {
6235   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6236   VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6237   VIXL_ASSERT(pd.IsLaneSizeB());
6238   Emit(ORRS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6239 }
6240 
sel(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6241 void Assembler::sel(const PRegisterWithLaneSize& pd,
6242                     const PRegister& pg,
6243                     const PRegisterWithLaneSize& pn,
6244                     const PRegisterWithLaneSize& pm) {
6245   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6246   Emit(SEL_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6247 }
6248 
6249 // SVEPredicateMisc.
6250 
pfalse(const PRegisterWithLaneSize & pd)6251 void Assembler::pfalse(const PRegisterWithLaneSize& pd) {
6252   // PFALSE <Pd>.B
6253   //  0010 0101 0001 1000 1110 0100 0000 ....
6254   //  op<23> = 0 | S<22> = 0 | Pd<3:0>
6255 
6256   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6257   // Ignore the lane size, since it makes no difference to the operation.
6258 
6259   Emit(PFALSE_p | Pd(pd));
6260 }
6261 
pfirst(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)6262 void Assembler::pfirst(const PRegisterWithLaneSize& pd,
6263                        const PRegister& pg,
6264                        const PRegisterWithLaneSize& pn) {
6265   // PFIRST <Pdn>.B, <Pg>, <Pdn>.B
6266   //  0010 0101 0101 1000 1100 000. ...0 ....
6267   //  op<23> = 0 | S<22> = 1 | Pg<8:5> | Pdn<3:0>
6268 
6269   USE(pn);
6270   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6271   VIXL_ASSERT(pd.Is(pn));
6272   VIXL_ASSERT(pd.IsLaneSizeB());
6273 
6274   Emit(PFIRST_p_p_p | Pd(pd) | Pg<8, 5>(pg));
6275 }
6276 
pnext(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)6277 void Assembler::pnext(const PRegisterWithLaneSize& pd,
6278                       const PRegister& pg,
6279                       const PRegisterWithLaneSize& pn) {
6280   // PNEXT <Pdn>.<T>, <Pg>, <Pdn>.<T>
6281   //  0010 0101 ..01 1001 1100 010. ...0 ....
6282   //  size<23:22> | Pg<8:5> | Pdn<3:0>
6283 
6284   USE(pn);
6285   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6286   VIXL_ASSERT(pd.Is(pn));
6287 
6288   Emit(PNEXT_p_p_p | SVESize(pd) | Pd(pd) | Pg<8, 5>(pg));
6289 }
6290 
ptest(const PRegister & pg,const PRegisterWithLaneSize & pn)6291 void Assembler::ptest(const PRegister& pg, const PRegisterWithLaneSize& pn) {
6292   // PTEST <Pg>, <Pn>.B
6293   //  0010 0101 0101 0000 11.. ..0. ...0 0000
6294   //  op<23> = 0 | S<22> = 1 | Pg<13:10> | Pn<8:5> | opc2<3:0> = 0000
6295 
6296   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6297   VIXL_ASSERT(pn.IsLaneSizeB());
6298 
6299   Emit(PTEST_p_p | Pg<13, 10>(pg) | Rx<8, 5>(pn));
6300 }
6301 
ptrue(const PRegisterWithLaneSize & pd,int pattern)6302 void Assembler::ptrue(const PRegisterWithLaneSize& pd, int pattern) {
6303   // PTRUE <Pd>.<T>{, <pattern>}
6304   //  0010 0101 ..01 1000 1110 00.. ...0 ....
6305   //  size<23:22> | S<16> = 0 | pattern<9:5> | Pd<3:0>
6306 
6307   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6308 
6309   Emit(PTRUE_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));
6310 }
6311 
ptrues(const PRegisterWithLaneSize & pd,int pattern)6312 void Assembler::ptrues(const PRegisterWithLaneSize& pd, int pattern) {
6313   // PTRUES <Pd>.<T>{, <pattern>}
6314   //  0010 0101 ..01 1001 1110 00.. ...0 ....
6315   //  size<23:22> | S<16> = 1 | pattern<9:5> | Pd<3:0>
6316 
6317   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6318 
6319   Emit(PTRUES_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));
6320 }
6321 
rdffr(const PRegisterWithLaneSize & pd)6322 void Assembler::rdffr(const PRegisterWithLaneSize& pd) {
6323   // RDFFR <Pd>.B
6324   //  0010 0101 0001 1001 1111 0000 0000 ....
6325   //  op<23> = 0 | S<22> = 0 | Pd<3:0>
6326 
6327   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6328 
6329   Emit(RDFFR_p_f | Pd(pd));
6330 }
6331 
rdffr(const PRegisterWithLaneSize & pd,const PRegisterZ & pg)6332 void Assembler::rdffr(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
6333   // RDFFR <Pd>.B, <Pg>/Z
6334   //  0010 0101 0001 1000 1111 000. ...0 ....
6335   //  op<23> = 0 | S<22> = 0 | Pg<8:5> | Pd<3:0>
6336 
6337   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6338 
6339   Emit(RDFFR_p_p_f | Pd(pd) | Pg<8, 5>(pg));
6340 }
6341 
rdffrs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg)6342 void Assembler::rdffrs(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
6343   // RDFFRS <Pd>.B, <Pg>/Z
6344   //  0010 0101 0101 1000 1111 000. ...0 ....
6345   //  op<23> = 0 | S<22> = 1 | Pg<8:5> | Pd<3:0>
6346 
6347   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6348 
6349   Emit(RDFFRS_p_p_f | Pd(pd) | Pg<8, 5>(pg));
6350 }
6351 
6352 // SVEPropagateBreak.
6353 
brkpa(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6354 void Assembler::brkpa(const PRegisterWithLaneSize& pd,
6355                       const PRegisterZ& pg,
6356                       const PRegisterWithLaneSize& pn,
6357                       const PRegisterWithLaneSize& pm) {
6358   // BRKPA <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6359   //  0010 0101 0000 .... 11.. ..0. ...0 ....
6360   //  op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |
6361   //  Pd<3:0>
6362 
6363   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6364 
6365   Emit(BRKPA_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6366 }
6367 
brkpas(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6368 void Assembler::brkpas(const PRegisterWithLaneSize& pd,
6369                        const PRegisterZ& pg,
6370                        const PRegisterWithLaneSize& pn,
6371                        const PRegisterWithLaneSize& pm) {
6372   // BRKPAS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6373   //  0010 0101 0100 .... 11.. ..0. ...0 ....
6374   //  op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |
6375   //  Pd<3:0>
6376 
6377   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6378 
6379   Emit(BRKPAS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6380 }
6381 
brkpb(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6382 void Assembler::brkpb(const PRegisterWithLaneSize& pd,
6383                       const PRegisterZ& pg,
6384                       const PRegisterWithLaneSize& pn,
6385                       const PRegisterWithLaneSize& pm) {
6386   // BRKPB <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6387   //  0010 0101 0000 .... 11.. ..0. ...1 ....
6388   //  op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |
6389   //  Pd<3:0>
6390 
6391   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6392 
6393   Emit(BRKPB_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6394 }
6395 
brkpbs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6396 void Assembler::brkpbs(const PRegisterWithLaneSize& pd,
6397                        const PRegisterZ& pg,
6398                        const PRegisterWithLaneSize& pn,
6399                        const PRegisterWithLaneSize& pm) {
6400   // BRKPBS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6401   //  0010 0101 0100 .... 11.. ..0. ...1 ....
6402   //  op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |
6403   //  Pd<3:0>
6404 
6405   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6406 
6407   Emit(BRKPBS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6408 }
6409 
6410 // SVEStackFrameAdjustment.
6411 
addpl(const Register & xd,const Register & xn,int imm6)6412 void Assembler::addpl(const Register& xd, const Register& xn, int imm6) {
6413   // ADDPL <Xd|SP>, <Xn|SP>, #<imm>
6414   //  0000 0100 011. .... 0101 0... .... ....
6415   //  op<22> = 1 | Rn<20:16> | imm6<10:5> | Rd<4:0>
6416 
6417   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6418   VIXL_ASSERT(xd.IsX());
6419   VIXL_ASSERT(xn.IsX());
6420 
6421   Emit(ADDPL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));
6422 }
6423 
addvl(const Register & xd,const Register & xn,int imm6)6424 void Assembler::addvl(const Register& xd, const Register& xn, int imm6) {
6425   // ADDVL <Xd|SP>, <Xn|SP>, #<imm>
6426   //  0000 0100 001. .... 0101 0... .... ....
6427   //  op<22> = 0 | Rn<20:16> | imm6<10:5> | Rd<4:0>
6428 
6429   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6430   VIXL_ASSERT(xd.IsX());
6431   VIXL_ASSERT(xn.IsX());
6432 
6433   Emit(ADDVL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));
6434 }
6435 
6436 // SVEStackFrameSize.
6437 
rdvl(const Register & xd,int imm6)6438 void Assembler::rdvl(const Register& xd, int imm6) {
6439   // RDVL <Xd>, #<imm>
6440   //  0000 0100 1011 1111 0101 0... .... ....
6441   //  op<22> = 0 | opc2<20:16> = 11111 | imm6<10:5> | Rd<4:0>
6442 
6443   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6444   VIXL_ASSERT(xd.IsX());
6445 
6446   Emit(RDVL_r_i | Rd(xd) | ImmField<10, 5>(imm6));
6447 }
6448 
6449 // SVEVectorSelect.
6450 
sel(const ZRegister & zd,const PRegister & pg,const ZRegister & zn,const ZRegister & zm)6451 void Assembler::sel(const ZRegister& zd,
6452                     const PRegister& pg,
6453                     const ZRegister& zn,
6454                     const ZRegister& zm) {
6455   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6456   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6457 
6458   Emit(SEL_z_p_zz | SVESize(zd) | Rd(zd) | Pg<13, 10>(pg) | Rn(zn) | Rm(zm));
6459 }
6460 
6461 // SVEWriteFFR.
6462 
setffr()6463 void Assembler::setffr() {
6464   // SETFFR
6465   //  0010 0101 0010 1100 1001 0000 0000 0000
6466   //  opc<23:22> = 00
6467 
6468   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6469 
6470   Emit(SETFFR_f);
6471 }
6472 
wrffr(const PRegisterWithLaneSize & pn)6473 void Assembler::wrffr(const PRegisterWithLaneSize& pn) {
6474   // WRFFR <Pn>.B
6475   //  0010 0101 0010 1000 1001 000. ...0 0000
6476   //  opc<23:22> = 00 | Pn<8:5>
6477 
6478   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6479 
6480   Emit(WRFFR_f_p | Rx<8, 5>(pn));
6481 }
6482 
6483 // Aliases.
6484 
bic(const ZRegister & zd,const ZRegister & zn,uint64_t imm)6485 void Assembler::bic(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6486   and_(zd, zn, ~imm);
6487 }
6488 
eon(const ZRegister & zd,const ZRegister & zn,uint64_t imm)6489 void Assembler::eon(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6490   eor(zd, zn, ~imm);
6491 }
6492 
orn(const ZRegister & zd,const ZRegister & zn,uint64_t imm)6493 void Assembler::orn(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6494   orr(zd, zn, ~imm);
6495 }
6496 
6497 
fmov(const ZRegister & zd,const PRegisterM & pg,double imm)6498 void Assembler::fmov(const ZRegister& zd, const PRegisterM& pg, double imm) {
6499   if (IsPositiveZero(imm)) {
6500     cpy(zd, pg, 0);
6501   } else {
6502     fcpy(zd, pg, imm);
6503   }
6504 }
6505 
fmov(const ZRegister & zd,double imm)6506 void Assembler::fmov(const ZRegister& zd, double imm) {
6507   if (IsPositiveZero(imm)) {
6508     dup(zd, imm);
6509   } else {
6510     fdup(zd, imm);
6511   }
6512 }
6513 
mov(const PRegister & pd,const PRegister & pn)6514 void Assembler::mov(const PRegister& pd, const PRegister& pn) {
6515   // If the inputs carry a lane size, they must match.
6516   VIXL_ASSERT((!pd.HasLaneSize() && !pn.HasLaneSize()) ||
6517               AreSameLaneSize(pd, pn));
6518   orr(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());
6519 }
6520 
mov(const PRegisterWithLaneSize & pd,const PRegisterM & pg,const PRegisterWithLaneSize & pn)6521 void Assembler::mov(const PRegisterWithLaneSize& pd,
6522                     const PRegisterM& pg,
6523                     const PRegisterWithLaneSize& pn) {
6524   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6525   sel(pd, pg, pn, pd);
6526 }
6527 
mov(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)6528 void Assembler::mov(const PRegisterWithLaneSize& pd,
6529                     const PRegisterZ& pg,
6530                     const PRegisterWithLaneSize& pn) {
6531   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6532   and_(pd, pg, pn, pn);
6533 }
6534 
mov(const ZRegister & zd,const PRegister & pg,int imm8,int shift)6535 void Assembler::mov(const ZRegister& zd,
6536                     const PRegister& pg,
6537                     int imm8,
6538                     int shift) {
6539   VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
6540   cpy(zd, pg, imm8, shift);
6541 }
6542 
mov(const ZRegister & zd,const Register & xn)6543 void Assembler::mov(const ZRegister& zd, const Register& xn) { dup(zd, xn); }
6544 
mov(const ZRegister & zd,const VRegister & vn)6545 void Assembler::mov(const ZRegister& zd, const VRegister& vn) {
6546   VIXL_ASSERT(vn.IsScalar());
6547   VIXL_ASSERT(AreSameLaneSize(zd, vn));
6548   dup(zd, vn.Z().WithSameLaneSizeAs(vn), 0);
6549 }
6550 
mov(const ZRegister & zd,const ZRegister & zn)6551 void Assembler::mov(const ZRegister& zd, const ZRegister& zn) {
6552   VIXL_ASSERT(AreSameLaneSize(zd, zn));
6553   orr(zd.VnD(), zn.VnD(), zn.VnD());
6554 }
6555 
mov(const ZRegister & zd,const ZRegister & zn,unsigned index)6556 void Assembler::mov(const ZRegister& zd, const ZRegister& zn, unsigned index) {
6557   VIXL_ASSERT(AreSameLaneSize(zd, zn));
6558   dup(zd, zn, index);
6559 }
6560 
mov(const ZRegister & zd,const PRegisterM & pg,const Register & rn)6561 void Assembler::mov(const ZRegister& zd,
6562                     const PRegisterM& pg,
6563                     const Register& rn) {
6564   cpy(zd, pg, rn);
6565 }
6566 
mov(const ZRegister & zd,const PRegisterM & pg,const VRegister & vn)6567 void Assembler::mov(const ZRegister& zd,
6568                     const PRegisterM& pg,
6569                     const VRegister& vn) {
6570   VIXL_ASSERT(vn.IsScalar());
6571   VIXL_ASSERT(AreSameLaneSize(zd, vn));
6572   cpy(zd, pg, vn);
6573 }
6574 
mov(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6575 void Assembler::mov(const ZRegister& zd,
6576                     const PRegisterM& pg,
6577                     const ZRegister& zn) {
6578   VIXL_ASSERT(AreSameLaneSize(zd, zn));
6579   sel(zd, pg, zn, zd);
6580 }
6581 
mov(const ZRegister & zd,uint64_t imm)6582 void Assembler::mov(const ZRegister& zd, uint64_t imm) {
6583   // Mov is an alias of dupm for certain values of imm. Whilst this matters in
6584   // the disassembler, for the assembler, we don't distinguish between the
6585   // two mnemonics, and simply call dupm.
6586   dupm(zd, imm);
6587 }
6588 
mov(const ZRegister & zd,int imm8,int shift)6589 void Assembler::mov(const ZRegister& zd, int imm8, int shift) {
6590   dup(zd, imm8, shift);
6591 }
6592 
movs(const PRegister & pd,const PRegister & pn)6593 void Assembler::movs(const PRegister& pd, const PRegister& pn) {
6594   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6595   orrs(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());
6596 }
6597 
movs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)6598 void Assembler::movs(const PRegisterWithLaneSize& pd,
6599                      const PRegisterZ& pg,
6600                      const PRegisterWithLaneSize& pn) {
6601   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6602   ands(pd, pg, pn, pn);
6603 }
6604 
not_(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)6605 void Assembler::not_(const PRegisterWithLaneSize& pd,
6606                      const PRegisterZ& pg,
6607                      const PRegisterWithLaneSize& pn) {
6608   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6609   eor(pd, pg, pn, pg.VnB());
6610 }
6611 
nots(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)6612 void Assembler::nots(const PRegisterWithLaneSize& pd,
6613                      const PRegisterZ& pg,
6614                      const PRegisterWithLaneSize& pn) {
6615   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6616   eors(pd, pg, pn, pg.VnB());
6617 }
6618 
6619 // SVE2
6620 
adclb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)6621 void Assembler::adclb(const ZRegister& zda,
6622                       const ZRegister& zn,
6623                       const ZRegister& zm) {
6624   // ADCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
6625   //  0100 0101 0.0. .... 1101 00.. .... ....
6626   //  size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
6627 
6628   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6629   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6630   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6631 
6632   Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
6633   Emit(0x4500d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));
6634 }
6635 
adclt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)6636 void Assembler::adclt(const ZRegister& zda,
6637                       const ZRegister& zn,
6638                       const ZRegister& zm) {
6639   // ADCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
6640   //  0100 0101 0.0. .... 1101 01.. .... ....
6641   //  size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
6642 
6643   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6644   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6645   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6646 
6647   Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
6648   Emit(0x4500d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));
6649 }
6650 
addhnb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6651 void Assembler::addhnb(const ZRegister& zd,
6652                        const ZRegister& zn,
6653                        const ZRegister& zm) {
6654   // ADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
6655   //  0100 0101 ..1. .... 0110 00.. .... ....
6656   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
6657 
6658   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6659   VIXL_ASSERT(AreSameLaneSize(zn, zm));
6660   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
6661   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
6662 
6663   Emit(0x45206000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
6664 }
6665 
addhnt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6666 void Assembler::addhnt(const ZRegister& zd,
6667                        const ZRegister& zn,
6668                        const ZRegister& zm) {
6669   // ADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
6670   //  0100 0101 ..1. .... 0110 01.. .... ....
6671   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
6672 
6673   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6674   VIXL_ASSERT(AreSameLaneSize(zn, zm));
6675   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
6676   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
6677 
6678   Emit(0x45206400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
6679 }
6680 
addp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)6681 void Assembler::addp(const ZRegister& zd,
6682                      const PRegisterM& pg,
6683                      const ZRegister& zn,
6684                      const ZRegister& zm) {
6685   // ADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
6686   //  0100 0100 ..01 0001 101. .... .... ....
6687   //  size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
6688 
6689   USE(zn);
6690   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6691   VIXL_ASSERT(zd.Is(zn));
6692   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6693 
6694   Emit(0x4411a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
6695 }
6696 
bcax(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)6697 void Assembler::bcax(const ZRegister& zd,
6698                      const ZRegister& zn,
6699                      const ZRegister& zm,
6700                      const ZRegister& zk) {
6701   // BCAX <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6702   //  0000 0100 011. .... 0011 10.. .... ....
6703   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6704 
6705   USE(zn);
6706   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6707   VIXL_ASSERT(zd.Is(zn));
6708   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6709   VIXL_ASSERT(zd.IsLaneSizeD());
6710 
6711   Emit(0x04603800 | Rd(zd) | Rm(zm) | Rn(zk));
6712 }
6713 
bdep(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6714 void Assembler::bdep(const ZRegister& zd,
6715                      const ZRegister& zn,
6716                      const ZRegister& zm) {
6717   // BDEP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6718   //  0100 0101 ..0. .... 1011 01.. .... ....
6719   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6720 
6721   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6722   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6723   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6724 
6725   Emit(0x4500b400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6726 }
6727 
bext(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6728 void Assembler::bext(const ZRegister& zd,
6729                      const ZRegister& zn,
6730                      const ZRegister& zm) {
6731   // BEXT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6732   //  0100 0101 ..0. .... 1011 00.. .... ....
6733   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6734 
6735   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6736   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6737   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6738 
6739   Emit(0x4500b000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6740 }
6741 
bgrp(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6742 void Assembler::bgrp(const ZRegister& zd,
6743                      const ZRegister& zn,
6744                      const ZRegister& zm) {
6745   // BGRP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6746   //  0100 0101 ..0. .... 1011 10.. .... ....
6747   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6748 
6749   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6750   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6751   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6752 
6753   Emit(0x4500b800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6754 }
6755 
bsl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)6756 void Assembler::bsl(const ZRegister& zd,
6757                     const ZRegister& zn,
6758                     const ZRegister& zm,
6759                     const ZRegister& zk) {
6760   // BSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6761   //  0000 0100 001. .... 0011 11.. .... ....
6762   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6763 
6764   USE(zn);
6765   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6766   VIXL_ASSERT(zd.Is(zn));
6767   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6768   VIXL_ASSERT(zd.IsLaneSizeD());
6769 
6770   Emit(0x04203c00 | Rd(zd) | Rm(zm) | Rn(zk));
6771 }
6772 
bsl1n(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)6773 void Assembler::bsl1n(const ZRegister& zd,
6774                       const ZRegister& zn,
6775                       const ZRegister& zm,
6776                       const ZRegister& zk) {
6777   // BSL1N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6778   //  0000 0100 011. .... 0011 11.. .... ....
6779   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6780 
6781   USE(zn);
6782   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6783   VIXL_ASSERT(zd.Is(zn));
6784   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6785   VIXL_ASSERT(zd.IsLaneSizeD());
6786 
6787   Emit(0x04603c00 | Rd(zd) | Rm(zm) | Rn(zk));
6788 }
6789 
bsl2n(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)6790 void Assembler::bsl2n(const ZRegister& zd,
6791                       const ZRegister& zn,
6792                       const ZRegister& zm,
6793                       const ZRegister& zk) {
6794   // BSL2N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6795   //  0000 0100 101. .... 0011 11.. .... ....
6796   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6797 
6798   USE(zn);
6799   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6800   VIXL_ASSERT(zd.Is(zn));
6801   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6802   VIXL_ASSERT(zd.IsLaneSizeD());
6803 
6804   Emit(0x04a03c00 | Rd(zd) | Rm(zm) | Rn(zk));
6805 }
6806 
cadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int rot)6807 void Assembler::cadd(const ZRegister& zd,
6808                      const ZRegister& zn,
6809                      const ZRegister& zm,
6810                      int rot) {
6811   // CADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>
6812   //  0100 0101 ..00 0000 1101 1... .... ....
6813   //  size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>
6814 
6815   USE(zn);
6816   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6817   VIXL_ASSERT(zd.Is(zn));
6818   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6819   VIXL_ASSERT((rot == 90) || (rot == 270));
6820 
6821   Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);
6822   Emit(0x4500d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));
6823 }
6824 
cdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index,int rot)6825 void Assembler::cdot(const ZRegister& zda,
6826                      const ZRegister& zn,
6827                      const ZRegister& zm,
6828                      int index,
6829                      int rot) {
6830   // CDOT <Zda>.D, <Zn>.H, <Zm>.H[<imm>], <const>
6831   //  0100 0100 111. .... 0100 .... .... ....
6832   //  size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6833 
6834   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6835   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6836   VIXL_ASSERT(AreSameLaneSize(zn, zm));
6837   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6838   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
6839   VIXL_ASSERT(index >= 0);
6840 
6841   Instr zm_and_idx = 0;
6842   if (zm.IsLaneSizeB()) {
6843     // Zm<18:16> | i2<20:19>
6844     VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 3));
6845     zm_and_idx = (index << 19) | Rx<18, 16>(zm);
6846   } else {
6847     // Zm<19:16> | i1<20>
6848     VIXL_ASSERT(zm.IsLaneSizeH());
6849     VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 1));
6850     zm_and_idx = (index << 20) | Rx<19, 16>(zm);
6851   }
6852 
6853   Instr rotate_bits = (rot / 90) << 10;
6854   Emit(0x44a04000 | zm_and_idx | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn));
6855 }
6856 
cdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int rot)6857 void Assembler::cdot(const ZRegister& zda,
6858                      const ZRegister& zn,
6859                      const ZRegister& zm,
6860                      int rot) {
6861   // CDOT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>, <const>
6862   //  0100 0100 ..0. .... 0001 .... .... ....
6863   //  size<23:22> | Zm<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6864 
6865   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6866   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6867   VIXL_ASSERT(AreSameLaneSize(zn, zm));
6868   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6869   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
6870 
6871   Instr rotate_bits = (rot / 90) << 10;
6872   Emit(0x44001000 | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
6873 }
6874 
cmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index,int rot)6875 void Assembler::cmla(const ZRegister& zda,
6876                      const ZRegister& zn,
6877                      const ZRegister& zm,
6878                      int index,
6879                      int rot) {
6880   // CMLA <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>
6881   //  0100 0100 101. .... 0110 .... .... ....
6882   //  size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6883 
6884   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6885   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6886   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6887 
6888   Instr rotate_bit = (rot / 90) << 10;
6889   Emit(0x44a06000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |
6890        Rn(zn));
6891 }
6892 
cmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int rot)6893 void Assembler::cmla(const ZRegister& zda,
6894                      const ZRegister& zn,
6895                      const ZRegister& zm,
6896                      int rot) {
6897   // CMLA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>
6898   //  0100 0100 ..0. .... 0010 .... .... ....
6899   //  size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>
6900 
6901   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6902   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6903   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6904 
6905   Instr rotate_bit = (rot / 90) << 10;
6906   Emit(0x44002000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
6907 }
6908 
eor3(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)6909 void Assembler::eor3(const ZRegister& zd,
6910                      const ZRegister& zn,
6911                      const ZRegister& zm,
6912                      const ZRegister& zk) {
6913   // EOR3 <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6914   //  0000 0100 001. .... 0011 10.. .... ....
6915   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6916 
6917   USE(zn);
6918   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6919   VIXL_ASSERT(zd.Is(zn));
6920   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6921   VIXL_ASSERT(zd.IsLaneSizeD());
6922 
6923   Emit(0x04203800 | Rd(zd) | Rm(zm) | Rn(zk));
6924 }
6925 
eorbt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6926 void Assembler::eorbt(const ZRegister& zd,
6927                       const ZRegister& zn,
6928                       const ZRegister& zm) {
6929   // EORBT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6930   //  0100 0101 ..0. .... 1001 00.. .... ....
6931   //  size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>
6932 
6933   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6934   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6935 
6936   Emit(0x45009000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6937 }
6938 
eortb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6939 void Assembler::eortb(const ZRegister& zd,
6940                       const ZRegister& zn,
6941                       const ZRegister& zm) {
6942   // EORTB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6943   //  0100 0101 ..0. .... 1001 01.. .... ....
6944   //  size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>
6945 
6946   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6947   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6948 
6949   Emit(0x45009400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6950 }
6951 
faddp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)6952 void Assembler::faddp(const ZRegister& zd,
6953                       const PRegisterM& pg,
6954                       const ZRegister& zn,
6955                       const ZRegister& zm) {
6956   // FADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
6957   //  0110 0100 ..01 0000 100. .... .... ....
6958   //  size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
6959 
6960   USE(zn);
6961   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6962   VIXL_ASSERT(zd.Is(zn));
6963   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6964   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
6965 
6966   Emit(0x64108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
6967 }
6968 
fcvtlt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6969 void Assembler::fcvtlt(const ZRegister& zd,
6970                        const PRegisterM& pg,
6971                        const ZRegister& zn) {
6972   // FCVTLT <Zd>.S, <Pg>/M, <Zn>.H
6973   //  0110 0100 1000 1001 101. .... .... ....
6974   //  opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
6975 
6976   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6977 
6978   Instr op;
6979   if (zd.IsLaneSizeD() && zn.IsLaneSizeS()) {
6980     op = 0x64cba000;
6981   } else {
6982     VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeH());
6983     op = 0x6489a000;
6984   }
6985 
6986   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
6987 }
6988 
fcvtnt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6989 void Assembler::fcvtnt(const ZRegister& zd,
6990                        const PRegisterM& pg,
6991                        const ZRegister& zn) {
6992   // FCVTNT <Zd>.S, <Pg>/M, <Zn>.D
6993   //  0110 0100 1100 1010 101. .... .... ....
6994   //  opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
6995 
6996   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6997 
6998   Instr op;
6999   if (zd.IsLaneSizeS() && zn.IsLaneSizeD()) {
7000     op = 0x64caa000;
7001   } else {
7002     VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS());
7003     op = 0x6488a000;
7004   }
7005   Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
7006 }
7007 
fcvtx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)7008 void Assembler::fcvtx(const ZRegister& zd,
7009                       const PRegisterM& pg,
7010                       const ZRegister& zn) {
7011   // FCVTX <Zd>.S, <Pg>/M, <Zn>.D
7012   //  0110 0101 0000 1010 101. .... .... ....
7013   //  opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7014 
7015   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7016   VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeD());
7017 
7018   Emit(0x650aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
7019 }
7020 
fcvtxnt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)7021 void Assembler::fcvtxnt(const ZRegister& zd,
7022                         const PRegisterM& pg,
7023                         const ZRegister& zn) {
7024   // FCVTXNT <Zd>.S, <Pg>/M, <Zn>.D
7025   //  0110 0100 0000 1010 101. .... .... ....
7026   //  opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7027 
7028   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7029 
7030   Emit(0x640aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
7031 }
7032 
flogb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)7033 void Assembler::flogb(const ZRegister& zd,
7034                       const PRegisterM& pg,
7035                       const ZRegister& zn) {
7036   // FLOGB <Zd>.<T>, <Pg>/M, <Zn>.<T>
7037   //  0110 0101 0001 1..0 101. .... .... ....
7038   //  opc<23:22> | opc2<18:17> | U<16> | Pg<12:10> | Zn<9:5> | Zd<4:0> | size<>
7039 
7040   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7041   VIXL_ASSERT(AreSameLaneSize(zd, zn));
7042   VIXL_ASSERT(!zd.IsLaneSizeB());
7043 
7044   // Size field is encoded in bits <18:17> rather than <23:22>.
7045   Instr size = SVESize(zd) >> 5;
7046   Emit(0x6518a000 | size | Rd(zd) | PgLow8(pg) | Rn(zn));
7047 }
7048 
fmaxnmp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7049 void Assembler::fmaxnmp(const ZRegister& zd,
7050                         const PRegisterM& pg,
7051                         const ZRegister& zn,
7052                         const ZRegister& zm) {
7053   // FMAXNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7054   //  0110 0100 ..01 0100 100. .... .... ....
7055   //  size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7056 
7057   USE(zn);
7058   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7059   VIXL_ASSERT(zd.Is(zn));
7060   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7061   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7062 
7063   Emit(0x64148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7064 }
7065 
fmaxp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7066 void Assembler::fmaxp(const ZRegister& zd,
7067                       const PRegisterM& pg,
7068                       const ZRegister& zn,
7069                       const ZRegister& zm) {
7070   // FMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7071   //  0110 0100 ..01 0110 100. .... .... ....
7072   //  size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7073 
7074   USE(zn);
7075   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7076   VIXL_ASSERT(zd.Is(zn));
7077   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7078   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7079 
7080   Emit(0x64168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7081 }
7082 
fminnmp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7083 void Assembler::fminnmp(const ZRegister& zd,
7084                         const PRegisterM& pg,
7085                         const ZRegister& zn,
7086                         const ZRegister& zm) {
7087   // FMINNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7088   //  0110 0100 ..01 0101 100. .... .... ....
7089   //  size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7090 
7091   USE(zn);
7092   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7093   VIXL_ASSERT(zd.Is(zn));
7094   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7095   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7096 
7097   Emit(0x64158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7098 }
7099 
fminp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7100 void Assembler::fminp(const ZRegister& zd,
7101                       const PRegisterM& pg,
7102                       const ZRegister& zn,
7103                       const ZRegister& zm) {
7104   // FMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7105   //  0110 0100 ..01 0111 100. .... .... ....
7106   //  size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7107 
7108   USE(zn);
7109   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7110   VIXL_ASSERT(zd.Is(zn));
7111   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7112   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7113 
7114   Emit(0x64178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7115 }
7116 
fmlalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7117 void Assembler::fmlalb(const ZRegister& zda,
7118                        const ZRegister& zn,
7119                        const ZRegister& zm) {
7120   // FMLALB <Zda>.S, <Zn>.H, <Zm>.H
7121   //  0110 0100 101. .... 1000 00.. .... ....
7122   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7123 
7124   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7125   VIXL_ASSERT(zda.IsLaneSizeS());
7126   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7127 
7128   Emit(0x64a08000 | Rd(zda) | Rn(zn) | Rm(zm));
7129 }
7130 
fmlalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7131 void Assembler::fmlalb(const ZRegister& zda,
7132                        const ZRegister& zn,
7133                        const ZRegister& zm,
7134                        int index) {
7135   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7136   VIXL_ASSERT(zda.IsLaneSizeS());
7137   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7138   VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7139   Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7140                      (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7141 
7142   Emit(0x64a04000 | Rd(zda) | Rn(zn) | zm_and_idx);
7143 }
7144 
fmlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7145 void Assembler::fmlalt(const ZRegister& zda,
7146                        const ZRegister& zn,
7147                        const ZRegister& zm) {
7148   // FMLALT <Zda>.S, <Zn>.H, <Zm>.H
7149   //  0110 0100 101. .... 1000 01.. .... ....
7150   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7151 
7152   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7153   VIXL_ASSERT(zda.IsLaneSizeS());
7154   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7155 
7156   Emit(0x64a08400 | Rd(zda) | Rn(zn) | Rm(zm));
7157 }
7158 
fmlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7159 void Assembler::fmlalt(const ZRegister& zda,
7160                        const ZRegister& zn,
7161                        const ZRegister& zm,
7162                        int index) {
7163   // FMLALT <Zda>.S, <Zn>.H, <Zm>.H
7164   //  0110 0100 101. .... 1000 01.. .... ....
7165   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7166 
7167   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7168   VIXL_ASSERT(zda.IsLaneSizeS());
7169   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7170   VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7171   Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7172                      (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7173 
7174   Emit(0x64a04400 | Rd(zda) | Rn(zn) | zm_and_idx);
7175 }
7176 
fmlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7177 void Assembler::fmlslb(const ZRegister& zda,
7178                        const ZRegister& zn,
7179                        const ZRegister& zm) {
7180   // FMLSLB <Zda>.S, <Zn>.H, <Zm>.H
7181   //  0110 0100 101. .... 1010 00.. .... ....
7182   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7183 
7184   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7185   VIXL_ASSERT(zda.IsLaneSizeS());
7186   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7187 
7188   Emit(0x64a0a000 | Rd(zda) | Rn(zn) | Rm(zm));
7189 }
7190 
fmlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7191 void Assembler::fmlslb(const ZRegister& zda,
7192                        const ZRegister& zn,
7193                        const ZRegister& zm,
7194                        int index) {
7195   // FMLSLB <Zda>.S, <Zn>.H, <Zm>.H
7196   //  0110 0100 101. .... 1010 00.. .... ....
7197   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7198 
7199   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7200   VIXL_ASSERT(zda.IsLaneSizeS());
7201   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7202   VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7203   Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7204                      (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7205 
7206   Emit(0x64a06000 | Rd(zda) | Rn(zn) | zm_and_idx);
7207 }
7208 
fmlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7209 void Assembler::fmlslt(const ZRegister& zda,
7210                        const ZRegister& zn,
7211                        const ZRegister& zm) {
7212   // FMLSLT <Zda>.S, <Zn>.H, <Zm>.H
7213   //  0110 0100 101. .... 1010 01.. .... ....
7214   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7215 
7216   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7217   VIXL_ASSERT(zda.IsLaneSizeS());
7218   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7219 
7220   Emit(0x64a0a400 | Rd(zda) | Rn(zn) | Rm(zm));
7221 }
7222 
fmlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7223 void Assembler::fmlslt(const ZRegister& zda,
7224                        const ZRegister& zn,
7225                        const ZRegister& zm,
7226                        int index) {
7227   // FMLSLT <Zda>.S, <Zn>.H, <Zm>.H
7228   //  0110 0100 101. .... 1010 01.. .... ....
7229   //  o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7230 
7231   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7232   VIXL_ASSERT(zda.IsLaneSizeS());
7233   VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7234   VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7235   Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7236                      (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7237 
7238   Emit(0x64a06400 | Rd(zda) | Rn(zn) | zm_and_idx);
7239 }
7240 
histcnt(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)7241 void Assembler::histcnt(const ZRegister& zd,
7242                         const PRegisterZ& pg,
7243                         const ZRegister& zn,
7244                         const ZRegister& zm) {
7245   // HISTCNT <Zd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7246   //  0100 0101 ..1. .... 110. .... .... ....
7247   //  size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7248 
7249   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7250   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7251   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
7252 
7253   Emit(0x4520c000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7254 }
7255 
histseg(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7256 void Assembler::histseg(const ZRegister& zd,
7257                         const ZRegister& zn,
7258                         const ZRegister& zm) {
7259   // HISTSEG <Zd>.B, <Zn>.B, <Zm>.B
7260   //  0100 0101 ..1. .... 1010 00.. .... ....
7261   //  size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>
7262 
7263   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7264   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7265   VIXL_ASSERT(zd.IsLaneSizeB());
7266 
7267   Emit(0x4520a000 | Rd(zd) | Rn(zn) | Rm(zm));
7268 }
7269 
match(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)7270 void Assembler::match(const PRegisterWithLaneSize& pd,
7271                       const PRegisterZ& pg,
7272                       const ZRegister& zn,
7273                       const ZRegister& zm) {
7274   // MATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7275   //  0100 0101 ..1. .... 100. .... ...0 ....
7276   //  size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>
7277 
7278   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7279   VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));
7280   VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());
7281 
7282   Emit(0x45208000 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7283 }
7284 
mla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7285 void Assembler::mla(const ZRegister& zda,
7286                     const ZRegister& zn,
7287                     const ZRegister& zm,
7288                     int index) {
7289   // MLA <Zda>.D, <Zn>.D, <Zm>.D[<imm>]
7290   //  0100 0100 111. .... 0000 10.. .... ....
7291   //  size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>
7292 
7293   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7294   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7295 
7296   Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
7297                                            zm,
7298                                            index,
7299                                            0x44200800,
7300                                            0x44a00800,
7301                                            0x44e00800);
7302 
7303   Emit(synthesised_op | Rd(zda) | Rn(zn));
7304 }
7305 
mls(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)7306 void Assembler::mls(const ZRegister& zda,
7307                     const ZRegister& zn,
7308                     const ZRegister& zm,
7309                     int index) {
7310   // MLS <Zda>.D, <Zn>.D, <Zm>.D[<imm>]
7311   //  0100 0100 111. .... 0000 11.. .... ....
7312   //  size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>
7313 
7314   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7315   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7316 
7317   Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
7318                                            zm,
7319                                            index,
7320                                            0x44200c00,
7321                                            0x44a00c00,
7322                                            0x44e00c00);
7323 
7324   Emit(synthesised_op | Rd(zda) | Rn(zn));
7325 }
7326 
mul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int index)7327 void Assembler::mul(const ZRegister& zd,
7328                     const ZRegister& zn,
7329                     const ZRegister& zm,
7330                     int index) {
7331   // MUL <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
7332   //  0100 0100 111. .... 1111 10.. .... ....
7333   //  size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>
7334 
7335   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7336   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7337 
7338   Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
7339                                            zm,
7340                                            index,
7341                                            0x4420f800,
7342                                            0x44a0f800,
7343                                            0x44e0f800);
7344 
7345   Emit(synthesised_op | Rd(zd) | Rn(zn));
7346 }
7347 
mul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7348 void Assembler::mul(const ZRegister& zd,
7349                     const ZRegister& zn,
7350                     const ZRegister& zm) {
7351   // MUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
7352   //  0000 0100 ..1. .... 0110 00.. .... ....
7353   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7354 
7355   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7356   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7357 
7358   Emit(0x04206000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7359 }
7360 
nbsl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,const ZRegister & zk)7361 void Assembler::nbsl(const ZRegister& zd,
7362                      const ZRegister& zn,
7363                      const ZRegister& zm,
7364                      const ZRegister& zk) {
7365   // NBSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
7366   //  0000 0100 111. .... 0011 11.. .... ....
7367   //  opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
7368 
7369   USE(zn);
7370   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7371   VIXL_ASSERT(zd.Is(zn));
7372   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
7373   VIXL_ASSERT(zd.IsLaneSizeD());
7374 
7375   Emit(0x04e03c00 | Rd(zd) | Rm(zm) | Rn(zk));
7376 }
7377 
nmatch(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)7378 void Assembler::nmatch(const PRegisterWithLaneSize& pd,
7379                        const PRegisterZ& pg,
7380                        const ZRegister& zn,
7381                        const ZRegister& zm) {
7382   // NMATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7383   //  0100 0101 ..1. .... 100. .... ...1 ....
7384   //  size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>
7385 
7386   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7387   VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));
7388   VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());
7389 
7390   Emit(0x45208010 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7391 }
7392 
pmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7393 void Assembler::pmul(const ZRegister& zd,
7394                      const ZRegister& zn,
7395                      const ZRegister& zm) {
7396   // PMUL <Zd>.B, <Zn>.B, <Zm>.B
7397   //  0000 0100 001. .... 0110 01.. .... ....
7398   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7399 
7400   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7401 
7402   Emit(0x04206400 | Rd(zd) | Rn(zn) | Rm(zm));
7403 }
7404 
pmullb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7405 void Assembler::pmullb(const ZRegister& zd,
7406                        const ZRegister& zn,
7407                        const ZRegister& zm) {
7408   // PMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7409   //  0100 0101 ..0. .... 0110 10.. .... ....
7410   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7411 
7412   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7413   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7414   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
7415   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7416   // SVEPmull128 is not supported
7417   VIXL_ASSERT(!zd.IsLaneSizeQ());
7418 
7419   Emit(0x45006800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7420 }
7421 
pmullt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7422 void Assembler::pmullt(const ZRegister& zd,
7423                        const ZRegister& zn,
7424                        const ZRegister& zm) {
7425   // PMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7426   //  0100 0101 ..0. .... 0110 11.. .... ....
7427   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7428 
7429   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7430   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7431   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
7432   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7433   // SVEPmull128 is not supported
7434   VIXL_ASSERT(!zd.IsLaneSizeQ());
7435 
7436   Emit(0x45006c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7437 }
7438 
raddhnb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7439 void Assembler::raddhnb(const ZRegister& zd,
7440                         const ZRegister& zn,
7441                         const ZRegister& zm) {
7442   // RADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7443   //  0100 0101 ..1. .... 0110 10.. .... ....
7444   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7445 
7446   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7447   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7448   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7449   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7450 
7451   Emit(0x45206800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7452 }
7453 
raddhnt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7454 void Assembler::raddhnt(const ZRegister& zd,
7455                         const ZRegister& zn,
7456                         const ZRegister& zm) {
7457   // RADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7458   //  0100 0101 ..1. .... 0110 11.. .... ....
7459   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7460 
7461   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7462   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7463   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7464   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7465 
7466   Emit(0x45206c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7467 }
7468 
7469 #define VIXL_SVE_SHR_LIST(V) \
7470   V(rshrnb, 0x45201800)      \
7471   V(rshrnt, 0x45201c00)      \
7472   V(shrnb, 0x45201000)       \
7473   V(shrnt, 0x45201400)       \
7474   V(sqrshrnb, 0x45202800)    \
7475   V(sqrshrnt, 0x45202c00)    \
7476   V(sqrshrunb, 0x45200800)   \
7477   V(sqrshrunt, 0x45200c00)   \
7478   V(sqshrnb, 0x45202000)     \
7479   V(sqshrnt, 0x45202400)     \
7480   V(sqshrunb, 0x45200000)    \
7481   V(sqshrunt, 0x45200400)    \
7482   V(uqrshrnb, 0x45203800)    \
7483   V(uqrshrnt, 0x45203c00)    \
7484   V(uqshrnb, 0x45203000)     \
7485   V(uqshrnt, 0x45203400)
7486 
7487 #define VIXL_DEFINE_ASM_FUNC(MNE, X)                                         \
7488   void Assembler::MNE(const ZRegister& zd, const ZRegister& zn, int shift) { \
7489     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));                                 \
7490     VIXL_ASSERT(!zd.IsLaneSizeD() && !zd.IsLaneSizeQ());                     \
7491     VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));   \
7492     Instr encoded_imm =                                                      \
7493         EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());         \
7494     SVEBitwiseShiftImmediate(zd, zn, encoded_imm, X);                        \
7495   }
VIXL_SVE_SHR_LIST(VIXL_DEFINE_ASM_FUNC)7496 VIXL_SVE_SHR_LIST(VIXL_DEFINE_ASM_FUNC)
7497 #undef VIXL_DEFINE_ASM_FUNC
7498 
7499 void Assembler::rsubhnb(const ZRegister& zd,
7500                         const ZRegister& zn,
7501                         const ZRegister& zm) {
7502   // RSUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7503   //  0100 0101 ..1. .... 0111 10.. .... ....
7504   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7505 
7506   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7507   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7508   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7509   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7510 
7511   Emit(0x45207800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7512 }
7513 
rsubhnt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7514 void Assembler::rsubhnt(const ZRegister& zd,
7515                         const ZRegister& zn,
7516                         const ZRegister& zm) {
7517   // RSUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7518   //  0100 0101 ..1. .... 0111 11.. .... ....
7519   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7520 
7521   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7522   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7523   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7524   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7525 
7526   Emit(0x45207c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7527 }
7528 
saba(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7529 void Assembler::saba(const ZRegister& zda,
7530                      const ZRegister& zn,
7531                      const ZRegister& zm) {
7532   // SABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7533   //  0100 0101 ..0. .... 1111 10.. .... ....
7534   //  size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>
7535 
7536   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7537   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7538 
7539   Emit(0x4500f800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7540 }
7541 
sabalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7542 void Assembler::sabalb(const ZRegister& zda,
7543                        const ZRegister& zn,
7544                        const ZRegister& zm) {
7545   // SABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7546   //  0100 0101 ..0. .... 1100 00.. .... ....
7547   //  size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7548 
7549   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7550   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7551   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7552   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7553 
7554   Emit(0x4500c000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7555 }
7556 
sabalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7557 void Assembler::sabalt(const ZRegister& zda,
7558                        const ZRegister& zn,
7559                        const ZRegister& zm) {
7560   // SABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7561   //  0100 0101 ..0. .... 1100 01.. .... ....
7562   //  size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7563 
7564   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7565   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7566   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7567   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7568 
7569   Emit(0x4500c400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7570 }
7571 
sabdlb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7572 void Assembler::sabdlb(const ZRegister& zd,
7573                        const ZRegister& zn,
7574                        const ZRegister& zm) {
7575   // SABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7576   //  0100 0101 ..0. .... 0011 00.. .... ....
7577   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7578   //  Zd<4:0>
7579 
7580   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7581   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7582   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7583   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7584 
7585   Emit(0x45003000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7586 }
7587 
sabdlt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7588 void Assembler::sabdlt(const ZRegister& zd,
7589                        const ZRegister& zn,
7590                        const ZRegister& zm) {
7591   // SABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7592   //  0100 0101 ..0. .... 0011 01.. .... ....
7593   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7594   //  Zd<4:0>
7595 
7596   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7597   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7598   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7599   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7600 
7601   Emit(0x45003400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7602 }
7603 
sadalp(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn)7604 void Assembler::sadalp(const ZRegister& zda,
7605                        const PRegisterM& pg,
7606                        const ZRegister& zn) {
7607   // SADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
7608   //  0100 0100 ..00 0100 101. .... .... ....
7609   //  size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>
7610 
7611   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7612   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7613   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7614 
7615   Emit(0x4404a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));
7616 }
7617 
saddlb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7618 void Assembler::saddlb(const ZRegister& zd,
7619                        const ZRegister& zn,
7620                        const ZRegister& zm) {
7621   // SADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7622   //  0100 0101 ..0. .... 0000 00.. .... ....
7623   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7624   //  Zd<4:0>
7625 
7626   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7627   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7628   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7629   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7630 
7631   Emit(0x45000000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7632 }
7633 
saddlbt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7634 void Assembler::saddlbt(const ZRegister& zd,
7635                         const ZRegister& zn,
7636                         const ZRegister& zm) {
7637   // SADDLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7638   //  0100 0101 ..0. .... 1000 00.. .... ....
7639   //  size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
7640 
7641   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7642   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7643   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7644   VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
7645 
7646   Emit(0x45008000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7647 }
7648 
saddlt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7649 void Assembler::saddlt(const ZRegister& zd,
7650                        const ZRegister& zn,
7651                        const ZRegister& zm) {
7652   // SADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7653   //  0100 0101 ..0. .... 0000 01.. .... ....
7654   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7655   //  Zd<4:0>
7656 
7657   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7658   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7659   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7660   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7661 
7662   Emit(0x45000400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7663 }
7664 
saddwb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7665 void Assembler::saddwb(const ZRegister& zd,
7666                        const ZRegister& zn,
7667                        const ZRegister& zm) {
7668   // SADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
7669   //  0100 0101 ..0. .... 0100 00.. .... ....
7670   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7671 
7672   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7673   VIXL_ASSERT(AreSameLaneSize(zd, zn));
7674   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
7675   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7676 
7677   Emit(0x45004000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7678 }
7679 
saddwt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7680 void Assembler::saddwt(const ZRegister& zd,
7681                        const ZRegister& zn,
7682                        const ZRegister& zm) {
7683   // SADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
7684   //  0100 0101 ..0. .... 0100 01.. .... ....
7685   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7686 
7687   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7688   VIXL_ASSERT(AreSameLaneSize(zd, zn));
7689   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
7690   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7691 
7692   Emit(0x45004400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7693 }
7694 
sbclb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7695 void Assembler::sbclb(const ZRegister& zda,
7696                       const ZRegister& zn,
7697                       const ZRegister& zm) {
7698   // SBCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7699   //  0100 0101 1.0. .... 1101 00.. .... ....
7700   //  size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
7701 
7702   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7703   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7704   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
7705 
7706   Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
7707   Emit(0x4580d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));
7708 }
7709 
sbclt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7710 void Assembler::sbclt(const ZRegister& zda,
7711                       const ZRegister& zn,
7712                       const ZRegister& zm) {
7713   // SBCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7714   //  0100 0101 1.0. .... 1101 01.. .... ....
7715   //  size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
7716 
7717   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7718   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7719   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
7720 
7721   Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
7722   Emit(0x4580d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));
7723 }
7724 
shadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7725 void Assembler::shadd(const ZRegister& zd,
7726                       const PRegisterM& pg,
7727                       const ZRegister& zn,
7728                       const ZRegister& zm) {
7729   // SHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7730   //  0100 0100 ..01 0000 100. .... .... ....
7731   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7732 
7733   USE(zn);
7734   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7735   VIXL_ASSERT(zd.Is(zn));
7736   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7737 
7738   Emit(0x44108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7739 }
7740 
shsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7741 void Assembler::shsub(const ZRegister& zd,
7742                       const PRegisterM& pg,
7743                       const ZRegister& zn,
7744                       const ZRegister& zm) {
7745   // SHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7746   //  0100 0100 ..01 0010 100. .... .... ....
7747   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7748 
7749   USE(zn);
7750   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7751   VIXL_ASSERT(zd.Is(zn));
7752   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7753 
7754   Emit(0x44128000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7755 }
7756 
shsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7757 void Assembler::shsubr(const ZRegister& zd,
7758                        const PRegisterM& pg,
7759                        const ZRegister& zn,
7760                        const ZRegister& zm) {
7761   // SHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7762   //  0100 0100 ..01 0110 100. .... .... ....
7763   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7764 
7765   USE(zn);
7766   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7767   VIXL_ASSERT(zd.Is(zn));
7768   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7769 
7770   Emit(0x44168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7771 }
7772 
sli(const ZRegister & zd,const ZRegister & zn,int shift)7773 void Assembler::sli(const ZRegister& zd, const ZRegister& zn, int shift) {
7774   // SLI <Zd>.<T>, <Zn>.<T>, #<const>
7775   //  0100 0101 ..0. .... 1111 01.. .... ....
7776   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>
7777 
7778   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7779   VIXL_ASSERT(AreSameLaneSize(zd, zn));
7780   Instr encoded_imm =
7781       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
7782 
7783   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f400);
7784 }
7785 
smaxp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7786 void Assembler::smaxp(const ZRegister& zd,
7787                       const PRegisterM& pg,
7788                       const ZRegister& zn,
7789                       const ZRegister& zm) {
7790   // SMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7791   //  0100 0100 ..01 0100 101. .... .... ....
7792   //  size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7793 
7794   USE(zn);
7795   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7796   VIXL_ASSERT(zd.Is(zn));
7797   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7798 
7799   Emit(0x4414a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7800 }
7801 
sminp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7802 void Assembler::sminp(const ZRegister& zd,
7803                       const PRegisterM& pg,
7804                       const ZRegister& zn,
7805                       const ZRegister& zm) {
7806   // SMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7807   //  0100 0100 ..01 0110 101. .... .... ....
7808   //  size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7809 
7810   USE(zn);
7811   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7812   VIXL_ASSERT(zd.Is(zn));
7813   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7814 
7815   Emit(0x4416a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7816 }
7817 
7818 #define VIXL_SVE_MULL_INDEX_LIST(V) \
7819   V(smullb, 0x44a0c000)             \
7820   V(smullt, 0x44a0c400)             \
7821   V(umullb, 0x44a0d000)             \
7822   V(umullt, 0x44a0d400)             \
7823   V(smlalb, 0x44a08000)             \
7824   V(smlalt, 0x44a08400)             \
7825   V(smlslb, 0x44a0a000)             \
7826   V(smlslt, 0x44a0a400)             \
7827   V(umlalb, 0x44a09000)             \
7828   V(umlalt, 0x44a09400)             \
7829   V(umlslb, 0x44a0b000)             \
7830   V(umlslt, 0x44a0b400)             \
7831   V(sqdmullb, 0x44a0e000)           \
7832   V(sqdmullt, 0x44a0e400)
7833 
7834 #define VIXL_DEFINE_ASM_FUNC(MNE, OP)                                     \
7835   void Assembler::MNE(const ZRegister& zda,                               \
7836                       const ZRegister& zn,                                \
7837                       const ZRegister& zm,                                \
7838                       int index) {                                        \
7839     VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));                              \
7840     VIXL_ASSERT(AreSameLaneSize(zn, zm));                                 \
7841     VIXL_ASSERT(zda.IsLaneSizeD() || zda.IsLaneSizeS());                  \
7842     VIXL_ASSERT(zda.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2); \
7843     Instr zm_with_index = SVEMulLongIndexHelper(zm, index);               \
7844     Emit(OP | SVESize(zda) | Rd(zda) | Rn(zn) | zm_with_index);           \
7845   }
VIXL_SVE_MULL_INDEX_LIST(VIXL_DEFINE_ASM_FUNC)7846 VIXL_SVE_MULL_INDEX_LIST(VIXL_DEFINE_ASM_FUNC)
7847 #undef VIXL_DEFINE_ASM_FuNC
7848 
7849 void Assembler::smlalb(const ZRegister& zda,
7850                        const ZRegister& zn,
7851                        const ZRegister& zm) {
7852   // SMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7853   //  0100 0100 ..0. .... 0100 00.. .... ....
7854   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7855 
7856   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7857   VIXL_ASSERT(!zda.IsLaneSizeB());
7858   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7859   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7860 
7861   Emit(0x44004000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7862 }
7863 
smlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7864 void Assembler::smlalt(const ZRegister& zda,
7865                        const ZRegister& zn,
7866                        const ZRegister& zm) {
7867   // SMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7868   //  0100 0100 ..0. .... 0100 01.. .... ....
7869   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7870 
7871   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7872   VIXL_ASSERT(!zda.IsLaneSizeB());
7873   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7874   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7875 
7876   Emit(0x44004400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7877 }
7878 
smlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7879 void Assembler::smlslb(const ZRegister& zda,
7880                        const ZRegister& zn,
7881                        const ZRegister& zm) {
7882   // SMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7883   //  0100 0100 ..0. .... 0101 00.. .... ....
7884   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7885 
7886   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7887   VIXL_ASSERT(!zda.IsLaneSizeB());
7888   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7889   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7890 
7891   Emit(0x44005000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7892 }
7893 
smlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)7894 void Assembler::smlslt(const ZRegister& zda,
7895                        const ZRegister& zn,
7896                        const ZRegister& zm) {
7897   // SMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7898   //  0100 0100 ..0. .... 0101 01.. .... ....
7899   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7900 
7901   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7902   VIXL_ASSERT(!zda.IsLaneSizeB());
7903   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7904   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7905 
7906   Emit(0x44005400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7907 }
7908 
smulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7909 void Assembler::smulh(const ZRegister& zd,
7910                       const ZRegister& zn,
7911                       const ZRegister& zm) {
7912   // SMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
7913   //  0000 0100 ..1. .... 0110 10.. .... ....
7914   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7915 
7916   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7917   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7918 
7919   Emit(0x04206800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7920 }
7921 
smullb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7922 void Assembler::smullb(const ZRegister& zd,
7923                        const ZRegister& zn,
7924                        const ZRegister& zm) {
7925   // SMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7926   //  0100 0101 ..0. .... 0111 00.. .... ....
7927   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7928 
7929   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7930   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7931   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
7932   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7933 
7934   Emit(0x45007000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7935 }
7936 
smullt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)7937 void Assembler::smullt(const ZRegister& zd,
7938                        const ZRegister& zn,
7939                        const ZRegister& zm) {
7940   // SMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7941   //  0100 0101 ..0. .... 0111 01.. .... ....
7942   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7943 
7944   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7945   VIXL_ASSERT(AreSameLaneSize(zn, zm));
7946   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
7947   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7948 
7949   Emit(0x45007400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7950 }
7951 
sqabs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)7952 void Assembler::sqabs(const ZRegister& zd,
7953                       const PRegisterM& pg,
7954                       const ZRegister& zn) {
7955   // SQABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
7956   //  0100 0100 ..00 1000 101. .... .... ....
7957   //  size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7958 
7959   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7960   VIXL_ASSERT(AreSameLaneSize(zd, zn));
7961 
7962   Emit(0x4408a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
7963 }
7964 
sqadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)7965 void Assembler::sqadd(const ZRegister& zd,
7966                       const PRegisterM& pg,
7967                       const ZRegister& zn,
7968                       const ZRegister& zm) {
7969   // SQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7970   //  0100 0100 ..01 1000 100. .... .... ....
7971   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7972 
7973   USE(zn);
7974   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7975   VIXL_ASSERT(zd.Is(zn));
7976   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7977 
7978   Emit(0x44188000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7979 }
7980 
sqcadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int rot)7981 void Assembler::sqcadd(const ZRegister& zd,
7982                        const ZRegister& zn,
7983                        const ZRegister& zm,
7984                        int rot) {
7985   // SQCADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>
7986   //  0100 0101 ..00 0001 1101 1... .... ....
7987   //  size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>
7988 
7989   USE(zn);
7990   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7991   VIXL_ASSERT(zd.Is(zn));
7992   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7993   VIXL_ASSERT((rot == 90) || (rot == 270));
7994 
7995   Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);
7996   Emit(0x4501d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));
7997 }
7998 
7999 // This prototype maps to 2 instruction encodings:
8000 //  sqdmlalb_z_zzzi_d
8001 //  sqdmlalb_z_zzzi_s
sqdmlalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8002 void Assembler::sqdmlalb(const ZRegister& zda,
8003                          const ZRegister& zn,
8004                          const ZRegister& zm,
8005                          int index) {
8006   // SQDMLALB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8007   //  0100 0100 111. .... 0010 .0.. .... ....
8008   //  size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8009 
8010   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8011   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8012   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8013   VIXL_ASSERT(index >= 0);
8014 
8015   Instr zm_and_idx = 0;
8016   if (zm.IsLaneSizeH()) {
8017     // Zm<18:16> | i3h<20:19> | i3l<11>
8018     VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8019     zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8020                  (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8021   } else {
8022     // Zm<19:16> | i2h<20> | i2l<11>
8023     VIXL_ASSERT(zm.IsLaneSizeS());
8024     VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8025     zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8026                  Rx<19, 16>(zm);
8027   }
8028 
8029   Emit(0x44202000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8030 }
8031 
sqdmlalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8032 void Assembler::sqdmlalb(const ZRegister& zda,
8033                          const ZRegister& zn,
8034                          const ZRegister& zm) {
8035   // SQDMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8036   //  0100 0100 ..0. .... 0110 00.. .... ....
8037   //  size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8038 
8039   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8040   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8041   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8042   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8043 
8044   Emit(0x44006000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8045 }
8046 
sqdmlalbt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8047 void Assembler::sqdmlalbt(const ZRegister& zda,
8048                           const ZRegister& zn,
8049                           const ZRegister& zm) {
8050   // SQDMLALBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8051   //  0100 0100 ..0. .... 0000 10.. .... ....
8052   //  size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8053 
8054   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8055   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8056   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8057   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8058 
8059   Emit(0x44000800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8060 }
8061 
8062 // This prototype maps to 2 instruction encodings:
8063 //  sqdmlalt_z_zzzi_d
8064 //  sqdmlalt_z_zzzi_s
sqdmlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8065 void Assembler::sqdmlalt(const ZRegister& zda,
8066                          const ZRegister& zn,
8067                          const ZRegister& zm,
8068                          int index) {
8069   // SQDMLALT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8070   //  0100 0100 111. .... 0010 .1.. .... ....
8071   //  size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8072 
8073   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8074   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8075   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8076   VIXL_ASSERT(index >= 0);
8077 
8078   Instr zm_and_idx = 0;
8079   if (zm.IsLaneSizeH()) {
8080     // Zm<18:16> | i3h<20:19> | i3l<11>
8081     VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8082     zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8083                  (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8084   } else {
8085     // Zm<19:16> | i2h<20> | i2l<11>
8086     VIXL_ASSERT(zm.IsLaneSizeS());
8087     VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8088     zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8089                  Rx<19, 16>(zm);
8090   }
8091 
8092   Emit(0x44202400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8093 }
8094 
sqdmlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8095 void Assembler::sqdmlalt(const ZRegister& zda,
8096                          const ZRegister& zn,
8097                          const ZRegister& zm) {
8098   // SQDMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8099   //  0100 0100 ..0. .... 0110 01.. .... ....
8100   //  size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8101 
8102   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8103   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8104   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8105   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8106 
8107   Emit(0x44006400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8108 }
8109 
8110 // This prototype maps to 2 instruction encodings:
8111 //  sqdmlslb_z_zzzi_d
8112 //  sqdmlslb_z_zzzi_s
sqdmlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8113 void Assembler::sqdmlslb(const ZRegister& zda,
8114                          const ZRegister& zn,
8115                          const ZRegister& zm,
8116                          int index) {
8117   // SQDMLSLB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8118   //  0100 0100 111. .... 0011 .0.. .... ....
8119   //  size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8120 
8121   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8122   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8123   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8124   VIXL_ASSERT(index >= 0);
8125 
8126   Instr zm_and_idx = 0;
8127   if (zm.IsLaneSizeH()) {
8128     // Zm<18:16> | i3h<20:19> | i3l<11>
8129     VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8130     zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8131                  (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8132   } else {
8133     // Zm<19:16> | i2h<20> | i2l<11>
8134     VIXL_ASSERT(zm.IsLaneSizeS());
8135     VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8136     zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8137                  Rx<19, 16>(zm);
8138   }
8139 
8140   Emit(0x44203000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8141 }
8142 
sqdmlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8143 void Assembler::sqdmlslb(const ZRegister& zda,
8144                          const ZRegister& zn,
8145                          const ZRegister& zm) {
8146   // SQDMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8147   //  0100 0100 ..0. .... 0110 10.. .... ....
8148   //  size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8149 
8150   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8151   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8152   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8153   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8154 
8155   Emit(0x44006800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8156 }
8157 
sqdmlslbt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8158 void Assembler::sqdmlslbt(const ZRegister& zda,
8159                           const ZRegister& zn,
8160                           const ZRegister& zm) {
8161   // SQDMLSLBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8162   //  0100 0100 ..0. .... 0000 11.. .... ....
8163   //  size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8164 
8165   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8166   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8167   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8168   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8169 
8170   Emit(0x44000c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8171 }
8172 
8173 // This prototype maps to 2 instruction encodings:
8174 //  sqdmlslt_z_zzzi_d
8175 //  sqdmlslt_z_zzzi_s
sqdmlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8176 void Assembler::sqdmlslt(const ZRegister& zda,
8177                          const ZRegister& zn,
8178                          const ZRegister& zm,
8179                          int index) {
8180   // SQDMLSLT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8181   //  0100 0100 111. .... 0011 .1.. .... ....
8182   //  size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8183 
8184   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8185   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8186   VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8187   VIXL_ASSERT(index >= 0);
8188 
8189   Instr zm_and_idx = 0;
8190   if (zm.IsLaneSizeH()) {
8191     // Zm<18:16> | i3h<20:19> | i3l<11>
8192     VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8193     zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8194                  (ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8195   } else {
8196     // Zm<19:16> | i2h<20> | i2l<11>
8197     VIXL_ASSERT(zm.IsLaneSizeS());
8198     VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8199     zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8200                  Rx<19, 16>(zm);
8201   }
8202 
8203   Emit(0x44203400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8204 }
8205 
sqdmlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8206 void Assembler::sqdmlslt(const ZRegister& zda,
8207                          const ZRegister& zn,
8208                          const ZRegister& zm) {
8209   // SQDMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8210   //  0100 0100 ..0. .... 0110 11.. .... ....
8211   //  size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8212 
8213   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8214   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8215   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8216   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8217 
8218   Emit(0x44006c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8219 }
8220 
sqdmulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int index)8221 void Assembler::sqdmulh(const ZRegister& zd,
8222                         const ZRegister& zn,
8223                         const ZRegister& zm,
8224                         int index) {
8225   // SQDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
8226   //  0100 0100 111. .... 1111 00.. .... ....
8227   //  size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8228 
8229   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8230   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8231 
8232   Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
8233                                            zm,
8234                                            index,
8235                                            0x4420f000,
8236                                            0x44a0f000,
8237                                            0x44e0f000);
8238 
8239   Emit(synthesised_op | Rd(zd) | Rn(zn));
8240 }
8241 
sqdmulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8242 void Assembler::sqdmulh(const ZRegister& zd,
8243                         const ZRegister& zn,
8244                         const ZRegister& zm) {
8245   // SQDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8246   //  0000 0100 ..1. .... 0111 00.. .... ....
8247   //  size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8248 
8249   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8250   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8251 
8252   Emit(0x04207000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8253 }
8254 
sqdmullb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8255 void Assembler::sqdmullb(const ZRegister& zd,
8256                          const ZRegister& zn,
8257                          const ZRegister& zm) {
8258   // SQDMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8259   //  0100 0101 ..0. .... 0110 00.. .... ....
8260   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8261 
8262   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8263   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8264   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
8265   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
8266 
8267   Emit(0x45006000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8268 }
8269 
sqdmullt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8270 void Assembler::sqdmullt(const ZRegister& zd,
8271                          const ZRegister& zn,
8272                          const ZRegister& zm) {
8273   // SQDMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8274   //  0100 0101 ..0. .... 0110 01.. .... ....
8275   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8276 
8277   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8278   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8279   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
8280   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
8281 
8282   Emit(0x45006400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8283 }
8284 
sqneg(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)8285 void Assembler::sqneg(const ZRegister& zd,
8286                       const PRegisterM& pg,
8287                       const ZRegister& zn) {
8288   // SQNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
8289   //  0100 0100 ..00 1001 101. .... .... ....
8290   //  size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
8291 
8292   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8293   VIXL_ASSERT(AreSameLaneSize(zd, zn));
8294 
8295   Emit(0x4409a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
8296 }
8297 
sqrdcmlah(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index,int rot)8298 void Assembler::sqrdcmlah(const ZRegister& zda,
8299                           const ZRegister& zn,
8300                           const ZRegister& zm,
8301                           int index,
8302                           int rot) {
8303   // SQRDCMLAH <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>
8304   //  0100 0100 101. .... 0111 .... .... ....
8305   //  size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
8306 
8307   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8308   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8309   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
8310 
8311   Instr rotate_bit = (rot / 90) << 10;
8312   Emit(0x44a07000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |
8313        Rn(zn));
8314 }
8315 
sqrdcmlah(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int rot)8316 void Assembler::sqrdcmlah(const ZRegister& zda,
8317                           const ZRegister& zn,
8318                           const ZRegister& zm,
8319                           int rot) {
8320   // SQRDCMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>
8321   //  0100 0100 ..0. .... 0011 .... .... ....
8322   //  size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>
8323 
8324   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8325   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8326   VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
8327 
8328   Instr rotate_bit = (rot / 90) << 10;
8329   Emit(0x44003000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8330 }
8331 
8332 // This prototype maps to 3 instruction encodings:
8333 //  sqrdmlah_z_zzzi_d
8334 //  sqrdmlah_z_zzzi_h
8335 //  sqrdmlah_z_zzzi_s
sqrdmlah(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8336 void Assembler::sqrdmlah(const ZRegister& zda,
8337                          const ZRegister& zn,
8338                          const ZRegister& zm,
8339                          int index) {
8340   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8341   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8342 
8343   Instr op_h = 0x44201000;
8344   Instr op_s = op_h | (1 << 23);
8345   Instr op_d = op_h | (3 << 22);
8346   // The encoding of opcode, index, Zm, and size are synthesized in this
8347   // variable.
8348   Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
8349                                            zm,
8350                                            index,
8351                                            op_h,
8352                                            op_s,
8353                                            op_d);
8354 
8355   Emit(synthesized_op | Rd(zda) | Rn(zn));
8356 }
8357 
sqrdmlah(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8358 void Assembler::sqrdmlah(const ZRegister& zda,
8359                          const ZRegister& zn,
8360                          const ZRegister& zm) {
8361   // SQRDMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8362   //  0100 0100 ..0. .... 0111 00.. .... ....
8363   //  size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8364 
8365   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8366   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8367 
8368   Emit(0x44007000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8369 }
8370 
8371 // This prototype maps to 3 instruction encodings:
8372 //  sqrdmlsh_z_zzzi_d
8373 //  sqrdmlsh_z_zzzi_h
8374 //  sqrdmlsh_z_zzzi_s
sqrdmlsh(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)8375 void Assembler::sqrdmlsh(const ZRegister& zda,
8376                          const ZRegister& zn,
8377                          const ZRegister& zm,
8378                          int index) {
8379   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8380   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8381 
8382   Instr op_h = 0x44201400;
8383   Instr op_s = op_h | (1 << 23);
8384   Instr op_d = op_h | (3 << 22);
8385   // The encoding of opcode, index, Zm, and size are synthesized in this
8386   // variable.
8387   Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
8388                                            zm,
8389                                            index,
8390                                            op_h,
8391                                            op_s,
8392                                            op_d);
8393 
8394   Emit(synthesized_op | Rd(zda) | Rn(zn));
8395 }
8396 
sqrdmlsh(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8397 void Assembler::sqrdmlsh(const ZRegister& zda,
8398                          const ZRegister& zn,
8399                          const ZRegister& zm) {
8400   // SQRDMLSH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8401   //  0100 0100 ..0. .... 0111 01.. .... ....
8402   //  size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8403 
8404   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8405   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8406 
8407   Emit(0x44007400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8408 }
8409 
sqrdmulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int index)8410 void Assembler::sqrdmulh(const ZRegister& zd,
8411                          const ZRegister& zn,
8412                          const ZRegister& zm,
8413                          int index) {
8414   // SQRDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
8415   //  0100 0100 111. .... 1111 01.. .... ....
8416   //  size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8417 
8418   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8419   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8420 
8421   Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
8422                                            zm,
8423                                            index,
8424                                            0x4420f400,
8425                                            0x44a0f400,
8426                                            0x44e0f400);
8427 
8428   Emit(synthesised_op | Rd(zd) | Rn(zn));
8429 }
8430 
sqrdmulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8431 void Assembler::sqrdmulh(const ZRegister& zd,
8432                          const ZRegister& zn,
8433                          const ZRegister& zm) {
8434   // SQRDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8435   //  0000 0100 ..1. .... 0111 01.. .... ....
8436   //  size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8437 
8438   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8439   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8440 
8441   Emit(0x04207400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8442 }
8443 
sqrshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8444 void Assembler::sqrshl(const ZRegister& zd,
8445                        const PRegisterM& pg,
8446                        const ZRegister& zn,
8447                        const ZRegister& zm) {
8448   // SQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8449   //  0100 0100 ..00 1010 100. .... .... ....
8450   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8451   //  Zdn<4:0>
8452 
8453   USE(zn);
8454   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8455   VIXL_ASSERT(zd.Is(zn));
8456   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8457 
8458   Emit(0x440a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8459 }
8460 
sqrshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8461 void Assembler::sqrshlr(const ZRegister& zd,
8462                         const PRegisterM& pg,
8463                         const ZRegister& zn,
8464                         const ZRegister& zm) {
8465   // SQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8466   //  0100 0100 ..00 1110 100. .... .... ....
8467   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8468   //  Zdn<4:0>
8469 
8470   USE(zn);
8471   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8472   VIXL_ASSERT(zd.Is(zn));
8473   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8474 
8475   Emit(0x440e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8476 }
8477 
sqshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)8478 void Assembler::sqshl(const ZRegister& zd,
8479                       const PRegisterM& pg,
8480                       const ZRegister& zn,
8481                       int shift) {
8482   // SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8483   //  0000 0100 ..00 0110 100. .... .... ....
8484   //  tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8485   //  imm3<7:5> | Zdn<4:0>
8486 
8487   USE(zn);
8488   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8489   VIXL_ASSERT(zd.Is(zn));
8490   Instr encoded_imm =
8491       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
8492   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04068000);
8493 }
8494 
sqshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8495 void Assembler::sqshl(const ZRegister& zd,
8496                       const PRegisterM& pg,
8497                       const ZRegister& zn,
8498                       const ZRegister& zm) {
8499   // SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8500   //  0100 0100 ..00 1000 100. .... .... ....
8501   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8502   //  Zdn<4:0>
8503 
8504   USE(zn);
8505   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8506   VIXL_ASSERT(zd.Is(zn));
8507   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8508 
8509   Emit(0x44088000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8510 }
8511 
sqshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8512 void Assembler::sqshlr(const ZRegister& zd,
8513                        const PRegisterM& pg,
8514                        const ZRegister& zn,
8515                        const ZRegister& zm) {
8516   // SQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8517   //  0100 0100 ..00 1100 100. .... .... ....
8518   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8519   //  Zdn<4:0>
8520 
8521   USE(zn);
8522   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8523   VIXL_ASSERT(zd.Is(zn));
8524   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8525 
8526   Emit(0x440c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8527 }
8528 
sqshlu(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)8529 void Assembler::sqshlu(const ZRegister& zd,
8530                        const PRegisterM& pg,
8531                        const ZRegister& zn,
8532                        int shift) {
8533   // SQSHLU <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8534   //  0000 0100 ..00 1111 100. .... .... ....
8535   //  tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8536   //  imm3<7:5> | Zdn<4:0>
8537 
8538   USE(zn);
8539   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8540   VIXL_ASSERT(zd.Is(zn));
8541 
8542   Instr encoded_imm =
8543       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
8544   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040f8000);
8545 }
8546 
sqsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8547 void Assembler::sqsub(const ZRegister& zd,
8548                       const PRegisterM& pg,
8549                       const ZRegister& zn,
8550                       const ZRegister& zm) {
8551   // SQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8552   //  0100 0100 ..01 1010 100. .... .... ....
8553   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8554 
8555   USE(zn);
8556   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8557   VIXL_ASSERT(zd.Is(zn));
8558   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8559 
8560   Emit(0x441a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8561 }
8562 
sqsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8563 void Assembler::sqsubr(const ZRegister& zd,
8564                        const PRegisterM& pg,
8565                        const ZRegister& zn,
8566                        const ZRegister& zm) {
8567   // SQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8568   //  0100 0100 ..01 1110 100. .... .... ....
8569   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8570 
8571   USE(zn);
8572   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8573   VIXL_ASSERT(zd.Is(zn));
8574   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8575 
8576   Emit(0x441e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8577 }
8578 
sqxtnb(const ZRegister & zd,const ZRegister & zn)8579 void Assembler::sqxtnb(const ZRegister& zd, const ZRegister& zn) {
8580   // SQXTNB <Zd>.<T>, <Zn>.<Tb>
8581   //  0100 0101 0.1. .000 0100 00.. .... ....
8582   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8583 
8584   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8585   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8586   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8587 
8588   // XTN instructions look like immediate shifts with zero shift distance.
8589   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8590   SVEBitwiseShiftImmediate(zd, zn, size, 0x45204000);
8591 }
8592 
sqxtnt(const ZRegister & zd,const ZRegister & zn)8593 void Assembler::sqxtnt(const ZRegister& zd, const ZRegister& zn) {
8594   // SQXTNT <Zd>.<T>, <Zn>.<Tb>
8595   //  0100 0101 0.1. .000 0100 01.. .... ....
8596   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8597 
8598   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8599   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8600   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8601 
8602   // XTN instructions look like immediate shifts with zero shift distance.
8603   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8604   SVEBitwiseShiftImmediate(zd, zn, size, 0x45204400);
8605 }
8606 
sqxtunb(const ZRegister & zd,const ZRegister & zn)8607 void Assembler::sqxtunb(const ZRegister& zd, const ZRegister& zn) {
8608   // SQXTUNB <Zd>.<T>, <Zn>.<Tb>
8609   //  0100 0101 0.1. .000 0101 00.. .... ....
8610   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8611 
8612   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8613   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8614   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8615 
8616   // XTN instructions look like immediate shifts with zero shift distance.
8617   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8618   SVEBitwiseShiftImmediate(zd, zn, size, 0x45205000);
8619 }
8620 
sqxtunt(const ZRegister & zd,const ZRegister & zn)8621 void Assembler::sqxtunt(const ZRegister& zd, const ZRegister& zn) {
8622   // SQXTUNT <Zd>.<T>, <Zn>.<Tb>
8623   //  0100 0101 0.1. .000 0101 01.. .... ....
8624   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8625 
8626   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8627   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8628   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8629 
8630   // XTN instructions look like immediate shifts with zero shift distance.
8631   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8632   SVEBitwiseShiftImmediate(zd, zn, size, 0x45205400);
8633 }
8634 
srhadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8635 void Assembler::srhadd(const ZRegister& zd,
8636                        const PRegisterM& pg,
8637                        const ZRegister& zn,
8638                        const ZRegister& zm) {
8639   // SRHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8640   //  0100 0100 ..01 0100 100. .... .... ....
8641   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8642 
8643   USE(zn);
8644   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8645   VIXL_ASSERT(zd.Is(zn));
8646   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8647 
8648   Emit(0x44148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8649 }
8650 
sri(const ZRegister & zd,const ZRegister & zn,int shift)8651 void Assembler::sri(const ZRegister& zd, const ZRegister& zn, int shift) {
8652   // SRI <Zd>.<T>, <Zn>.<T>, #<const>
8653   //  0100 0101 ..0. .... 1111 00.. .... ....
8654   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>
8655 
8656   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8657   VIXL_ASSERT(AreSameLaneSize(zd, zn));
8658   Instr encoded_imm =
8659       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
8660 
8661   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f000);
8662 }
8663 
srshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8664 void Assembler::srshl(const ZRegister& zd,
8665                       const PRegisterM& pg,
8666                       const ZRegister& zn,
8667                       const ZRegister& zm) {
8668   // SRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8669   //  0100 0100 ..00 0010 100. .... .... ....
8670   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8671   //  Zdn<4:0>
8672 
8673   USE(zn);
8674   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8675   VIXL_ASSERT(zd.Is(zn));
8676   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8677 
8678   Emit(0x44028000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8679 }
8680 
srshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8681 void Assembler::srshlr(const ZRegister& zd,
8682                        const PRegisterM& pg,
8683                        const ZRegister& zn,
8684                        const ZRegister& zm) {
8685   // SRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8686   //  0100 0100 ..00 0110 100. .... .... ....
8687   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8688   //  Zdn<4:0>
8689 
8690   USE(zn);
8691   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8692   VIXL_ASSERT(zd.Is(zn));
8693   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8694 
8695   Emit(0x44068000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8696 }
8697 
srshr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)8698 void Assembler::srshr(const ZRegister& zd,
8699                       const PRegisterM& pg,
8700                       const ZRegister& zn,
8701                       int shift) {
8702   // SRSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8703   //  0000 0100 ..00 1100 100. .... .... ....
8704   //  tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8705   //  imm3<7:5> | Zdn<4:0>
8706 
8707   USE(zn);
8708   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8709   VIXL_ASSERT(zd.Is(zn));
8710   Instr encoded_imm =
8711       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
8712   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040c8000);
8713 }
8714 
srsra(const ZRegister & zda,const ZRegister & zn,int shift)8715 void Assembler::srsra(const ZRegister& zda, const ZRegister& zn, int shift) {
8716   // SRSRA <Zda>.<T>, <Zn>.<T>, #<const>
8717   //  0100 0101 ..0. .... 1110 10.. .... ....
8718   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
8719   //  Zda<4:0>
8720 
8721   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8722   VIXL_ASSERT(AreSameLaneSize(zda, zn));
8723   Instr encoded_imm =
8724       EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
8725 
8726   SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e800);
8727 }
8728 
sshllb(const ZRegister & zd,const ZRegister & zn,int shift)8729 void Assembler::sshllb(const ZRegister& zd, const ZRegister& zn, int shift) {
8730   // SSHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>
8731   //  0100 0101 0.0. .... 1010 00.. .... ....
8732   //  tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8733 
8734   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8735   VIXL_ASSERT(!zd.IsLaneSizeB());
8736   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8737 
8738   Instr encoded_imm =
8739       EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
8740   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a000);
8741 }
8742 
sshllt(const ZRegister & zd,const ZRegister & zn,int shift)8743 void Assembler::sshllt(const ZRegister& zd, const ZRegister& zn, int shift) {
8744   // SSHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>
8745   //  0100 0101 0.0. .... 1010 01.. .... ....
8746   //  tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8747 
8748   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8749   VIXL_ASSERT(!zd.IsLaneSizeB());
8750   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8751 
8752   Instr encoded_imm =
8753       EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
8754   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a400);
8755 }
8756 
ssra(const ZRegister & zda,const ZRegister & zn,int shift)8757 void Assembler::ssra(const ZRegister& zda, const ZRegister& zn, int shift) {
8758   // SSRA <Zda>.<T>, <Zn>.<T>, #<const>
8759   //  0100 0101 ..0. .... 1110 00.. .... ....
8760   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
8761   //  Zda<4:0>
8762 
8763   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8764   VIXL_ASSERT(AreSameLaneSize(zda, zn));
8765   Instr encoded_imm =
8766       EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
8767 
8768   SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e000);
8769 }
8770 
ssublb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8771 void Assembler::ssublb(const ZRegister& zd,
8772                        const ZRegister& zn,
8773                        const ZRegister& zm) {
8774   // SSUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8775   //  0100 0101 ..0. .... 0001 00.. .... ....
8776   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
8777   //  Zd<4:0>
8778 
8779   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8780   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8781   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8782   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8783 
8784   Emit(0x45001000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8785 }
8786 
ssublbt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8787 void Assembler::ssublbt(const ZRegister& zd,
8788                         const ZRegister& zn,
8789                         const ZRegister& zm) {
8790   // SSUBLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8791   //  0100 0101 ..0. .... 1000 10.. .... ....
8792   //  size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
8793 
8794   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8795   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8796   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8797   VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
8798 
8799   Emit(0x45008800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8800 }
8801 
ssublt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8802 void Assembler::ssublt(const ZRegister& zd,
8803                        const ZRegister& zn,
8804                        const ZRegister& zm) {
8805   // SSUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8806   //  0100 0101 ..0. .... 0001 01.. .... ....
8807   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
8808   //  Zd<4:0>
8809 
8810   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8811   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8812   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8813   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8814 
8815   Emit(0x45001400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8816 }
8817 
ssubltb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8818 void Assembler::ssubltb(const ZRegister& zd,
8819                         const ZRegister& zn,
8820                         const ZRegister& zm) {
8821   // SSUBLTB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8822   //  0100 0101 ..0. .... 1000 11.. .... ....
8823   //  size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
8824 
8825   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8826   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8827   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8828   VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
8829 
8830   Emit(0x45008c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8831 }
8832 
ssubwb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8833 void Assembler::ssubwb(const ZRegister& zd,
8834                        const ZRegister& zn,
8835                        const ZRegister& zm) {
8836   // SSUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
8837   //  0100 0101 ..0. .... 0101 00.. .... ....
8838   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8839 
8840   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8841   VIXL_ASSERT(AreSameLaneSize(zd, zn));
8842   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
8843   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8844 
8845   Emit(0x45005000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8846 }
8847 
ssubwt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8848 void Assembler::ssubwt(const ZRegister& zd,
8849                        const ZRegister& zn,
8850                        const ZRegister& zm) {
8851   // SSUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
8852   //  0100 0101 ..0. .... 0101 01.. .... ....
8853   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8854 
8855   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8856   VIXL_ASSERT(AreSameLaneSize(zd, zn));
8857   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
8858   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8859 
8860   Emit(0x45005400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8861 }
8862 
8863 #if 0
8864 // This prototype maps to 2 instruction encodings:
8865 //  stnt1b_z_p_ar_d_64_unscaled
8866 //  stnt1b_z_p_ar_s_x32_unscaled
8867 void Assembler::stnt1b(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8868   // STNT1B { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8869   //  1110 0100 000. .... 001. .... .... ....
8870   //  msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8871 
8872   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8873 
8874   Emit(0xe4002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8875 }
8876 
8877 void Assembler::stnt1d(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8878   // STNT1D { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8879   //  1110 0101 100. .... 001. .... .... ....
8880   //  msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8881 
8882   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8883 
8884   Emit(0xe5802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8885 }
8886 
8887 // This prototype maps to 2 instruction encodings:
8888 //  stnt1h_z_p_ar_d_64_unscaled
8889 //  stnt1h_z_p_ar_s_x32_unscaled
8890 void Assembler::stnt1h(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8891   // STNT1H { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8892   //  1110 0100 100. .... 001. .... .... ....
8893   //  msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8894 
8895   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8896 
8897   Emit(0xe4802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8898 }
8899 
8900 // This prototype maps to 2 instruction encodings:
8901 //  stnt1w_z_p_ar_d_64_unscaled
8902 //  stnt1w_z_p_ar_s_x32_unscaled
8903 void Assembler::stnt1w(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8904   // STNT1W { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8905   //  1110 0101 000. .... 001. .... .... ....
8906   //  msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8907 
8908   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8909 
8910   Emit(0xe5002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8911 }
8912 #endif
8913 
subhnb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8914 void Assembler::subhnb(const ZRegister& zd,
8915                        const ZRegister& zn,
8916                        const ZRegister& zm) {
8917   // SUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8918   //  0100 0101 ..1. .... 0111 00.. .... ....
8919   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
8920 
8921   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8922   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8923   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
8924   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
8925 
8926   Emit(0x45207000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
8927 }
8928 
subhnt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8929 void Assembler::subhnt(const ZRegister& zd,
8930                        const ZRegister& zn,
8931                        const ZRegister& zm) {
8932   // SUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8933   //  0100 0101 ..1. .... 0111 01.. .... ....
8934   //  size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
8935 
8936   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8937   VIXL_ASSERT(AreSameLaneSize(zn, zm));
8938   VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
8939   VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
8940 
8941   Emit(0x45207400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
8942 }
8943 
suqadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)8944 void Assembler::suqadd(const ZRegister& zd,
8945                        const PRegisterM& pg,
8946                        const ZRegister& zn,
8947                        const ZRegister& zm) {
8948   // SUQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8949   //  0100 0100 ..01 1100 100. .... .... ....
8950   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8951 
8952   USE(zn);
8953   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8954   VIXL_ASSERT(zd.Is(zn));
8955   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8956 
8957   Emit(0x441c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8958 }
8959 
tbl(const ZRegister & zd,const ZRegister & zn1,const ZRegister & zn2,const ZRegister & zm)8960 void Assembler::tbl(const ZRegister& zd,
8961                     const ZRegister& zn1,
8962                     const ZRegister& zn2,
8963                     const ZRegister& zm) {
8964   // TBL <Zd>.<T>, { <Zn1>.<T>, <Zn2>.<T> }, <Zm>.<T>
8965   //  0000 0101 ..1. .... 0010 10.. .... ....
8966   //  size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>
8967 
8968   USE(zn2);
8969   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8970   VIXL_ASSERT(AreConsecutive(zn1, zn2));
8971   VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2, zm));
8972 
8973   Emit(0x05202800 | SVESize(zd) | Rd(zd) | Rn(zn1) | Rn(zn2) | Rm(zm));
8974 }
8975 
tbx(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)8976 void Assembler::tbx(const ZRegister& zd,
8977                     const ZRegister& zn,
8978                     const ZRegister& zm) {
8979   // TBX <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8980   //  0000 0101 ..1. .... 0010 11.. .... ....
8981   //  size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>
8982 
8983   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8984   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8985 
8986   Emit(0x05202c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8987 }
8988 
uaba(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)8989 void Assembler::uaba(const ZRegister& zda,
8990                      const ZRegister& zn,
8991                      const ZRegister& zm) {
8992   // UABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8993   //  0100 0101 ..0. .... 1111 11.. .... ....
8994   //  size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>
8995 
8996   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8997   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8998 
8999   Emit(0x4500fc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9000 }
9001 
uabalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9002 void Assembler::uabalb(const ZRegister& zda,
9003                        const ZRegister& zn,
9004                        const ZRegister& zm) {
9005   // UABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9006   //  0100 0101 ..0. .... 1100 10.. .... ....
9007   //  size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9008 
9009   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9010   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9011   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9012   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9013 
9014   Emit(0x4500c800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9015 }
9016 
uabalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9017 void Assembler::uabalt(const ZRegister& zda,
9018                        const ZRegister& zn,
9019                        const ZRegister& zm) {
9020   // UABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9021   //  0100 0101 ..0. .... 1100 11.. .... ....
9022   //  size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9023 
9024   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9025   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9026   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9027   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9028 
9029   Emit(0x4500cc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9030 }
9031 
uabdlb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9032 void Assembler::uabdlb(const ZRegister& zd,
9033                        const ZRegister& zn,
9034                        const ZRegister& zm) {
9035   // UABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9036   //  0100 0101 ..0. .... 0011 10.. .... ....
9037   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9038   //  Zd<4:0>
9039 
9040   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9041   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9042   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9043   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9044 
9045   Emit(0x45003800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9046 }
9047 
uabdlt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9048 void Assembler::uabdlt(const ZRegister& zd,
9049                        const ZRegister& zn,
9050                        const ZRegister& zm) {
9051   // UABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9052   //  0100 0101 ..0. .... 0011 11.. .... ....
9053   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9054   //  Zd<4:0>
9055 
9056   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9057   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9058   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9059   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9060 
9061   Emit(0x45003c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9062 }
9063 
uadalp(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn)9064 void Assembler::uadalp(const ZRegister& zda,
9065                        const PRegisterM& pg,
9066                        const ZRegister& zn) {
9067   // UADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
9068   //  0100 0100 ..00 0101 101. .... .... ....
9069   //  size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>
9070 
9071   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9072   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9073   VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9074 
9075   Emit(0x4405a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));
9076 }
9077 
uaddlb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9078 void Assembler::uaddlb(const ZRegister& zd,
9079                        const ZRegister& zn,
9080                        const ZRegister& zm) {
9081   // UADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9082   //  0100 0101 ..0. .... 0000 10.. .... ....
9083   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9084   //  Zd<4:0>
9085 
9086   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9087   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9088   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9089   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9090 
9091   Emit(0x45000800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9092 }
9093 
uaddlt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9094 void Assembler::uaddlt(const ZRegister& zd,
9095                        const ZRegister& zn,
9096                        const ZRegister& zm) {
9097   // UADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9098   //  0100 0101 ..0. .... 0000 11.. .... ....
9099   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9100   //  Zd<4:0>
9101 
9102   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9103   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9104   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9105   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9106 
9107   Emit(0x45000c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9108 }
9109 
uaddwb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9110 void Assembler::uaddwb(const ZRegister& zd,
9111                        const ZRegister& zn,
9112                        const ZRegister& zm) {
9113   // UADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9114   //  0100 0101 ..0. .... 0100 10.. .... ....
9115   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9116 
9117   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9118   VIXL_ASSERT(AreSameLaneSize(zd, zn));
9119   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9120   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9121 
9122   Emit(0x45004800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9123 }
9124 
uaddwt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9125 void Assembler::uaddwt(const ZRegister& zd,
9126                        const ZRegister& zn,
9127                        const ZRegister& zm) {
9128   // UADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9129   //  0100 0101 ..0. .... 0100 11.. .... ....
9130   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9131 
9132   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9133   VIXL_ASSERT(AreSameLaneSize(zd, zn));
9134   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9135   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9136 
9137   Emit(0x45004c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9138 }
9139 
uhadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9140 void Assembler::uhadd(const ZRegister& zd,
9141                       const PRegisterM& pg,
9142                       const ZRegister& zn,
9143                       const ZRegister& zm) {
9144   // UHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9145   //  0100 0100 ..01 0001 100. .... .... ....
9146   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9147 
9148   USE(zn);
9149   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9150   VIXL_ASSERT(zd.Is(zn));
9151   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9152 
9153   Emit(0x44118000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9154 }
9155 
uhsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9156 void Assembler::uhsub(const ZRegister& zd,
9157                       const PRegisterM& pg,
9158                       const ZRegister& zn,
9159                       const ZRegister& zm) {
9160   // UHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9161   //  0100 0100 ..01 0011 100. .... .... ....
9162   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9163 
9164   USE(zn);
9165   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9166   VIXL_ASSERT(zd.Is(zn));
9167   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9168 
9169   Emit(0x44138000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9170 }
9171 
uhsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9172 void Assembler::uhsubr(const ZRegister& zd,
9173                        const PRegisterM& pg,
9174                        const ZRegister& zn,
9175                        const ZRegister& zm) {
9176   // UHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9177   //  0100 0100 ..01 0111 100. .... .... ....
9178   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9179 
9180   USE(zn);
9181   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9182   VIXL_ASSERT(zd.Is(zn));
9183   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9184 
9185   Emit(0x44178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9186 }
9187 
umaxp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9188 void Assembler::umaxp(const ZRegister& zd,
9189                       const PRegisterM& pg,
9190                       const ZRegister& zn,
9191                       const ZRegister& zm) {
9192   // UMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9193   //  0100 0100 ..01 0101 101. .... .... ....
9194   //  size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9195 
9196   USE(zn);
9197   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9198   VIXL_ASSERT(zd.Is(zn));
9199   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9200 
9201   Emit(0x4415a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9202 }
9203 
uminp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9204 void Assembler::uminp(const ZRegister& zd,
9205                       const PRegisterM& pg,
9206                       const ZRegister& zn,
9207                       const ZRegister& zm) {
9208   // UMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9209   //  0100 0100 ..01 0111 101. .... .... ....
9210   //  size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9211 
9212   USE(zn);
9213   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9214   VIXL_ASSERT(zd.Is(zn));
9215   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9216 
9217   Emit(0x4417a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9218 }
9219 
umlalb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9220 void Assembler::umlalb(const ZRegister& zda,
9221                        const ZRegister& zn,
9222                        const ZRegister& zm) {
9223   // UMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9224   //  0100 0100 ..0. .... 0100 10.. .... ....
9225   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9226 
9227   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9228   VIXL_ASSERT(!zda.IsLaneSizeB());
9229   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9230   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9231 
9232   Emit(0x44004800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9233 }
9234 
umlalt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9235 void Assembler::umlalt(const ZRegister& zda,
9236                        const ZRegister& zn,
9237                        const ZRegister& zm) {
9238   // UMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9239   //  0100 0100 ..0. .... 0100 11.. .... ....
9240   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9241 
9242   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9243   VIXL_ASSERT(!zda.IsLaneSizeB());
9244   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9245   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9246 
9247   Emit(0x44004c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9248 }
9249 
umlslb(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9250 void Assembler::umlslb(const ZRegister& zda,
9251                        const ZRegister& zn,
9252                        const ZRegister& zm) {
9253   // UMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9254   //  0100 0100 ..0. .... 0101 10.. .... ....
9255   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9256 
9257   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9258   VIXL_ASSERT(!zda.IsLaneSizeB());
9259   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9260   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9261 
9262   Emit(0x44005800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9263 }
9264 
umlslt(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9265 void Assembler::umlslt(const ZRegister& zda,
9266                        const ZRegister& zn,
9267                        const ZRegister& zm) {
9268   // UMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9269   //  0100 0100 ..0. .... 0101 11.. .... ....
9270   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9271 
9272   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9273   VIXL_ASSERT(!zda.IsLaneSizeB());
9274   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9275   VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9276 
9277   Emit(0x44005c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9278 }
9279 
umulh(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9280 void Assembler::umulh(const ZRegister& zd,
9281                       const ZRegister& zn,
9282                       const ZRegister& zm) {
9283   // UMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
9284   //  0000 0100 ..1. .... 0110 11.. .... ....
9285   //  size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
9286 
9287   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9288   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9289 
9290   Emit(0x04206c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9291 }
9292 
umullb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9293 void Assembler::umullb(const ZRegister& zd,
9294                        const ZRegister& zn,
9295                        const ZRegister& zm) {
9296   // UMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9297   //  0100 0101 ..0. .... 0111 10.. .... ....
9298   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9299 
9300   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9301   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9302   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
9303   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
9304 
9305   Emit(0x45007800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9306 }
9307 
umullt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9308 void Assembler::umullt(const ZRegister& zd,
9309                        const ZRegister& zn,
9310                        const ZRegister& zm) {
9311   // UMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9312   //  0100 0101 ..0. .... 0111 11.. .... ....
9313   //  size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9314 
9315   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9316   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9317   VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
9318   VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
9319 
9320   Emit(0x45007c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9321 }
9322 
uqadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9323 void Assembler::uqadd(const ZRegister& zd,
9324                       const PRegisterM& pg,
9325                       const ZRegister& zn,
9326                       const ZRegister& zm) {
9327   // UQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9328   //  0100 0100 ..01 1001 100. .... .... ....
9329   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9330 
9331   USE(zn);
9332   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9333   VIXL_ASSERT(zd.Is(zn));
9334   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9335 
9336   Emit(0x44198000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9337 }
9338 
uqrshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9339 void Assembler::uqrshl(const ZRegister& zd,
9340                        const PRegisterM& pg,
9341                        const ZRegister& zn,
9342                        const ZRegister& zm) {
9343   // UQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9344   //  0100 0100 ..00 1011 100. .... .... ....
9345   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9346   //  Zdn<4:0>
9347 
9348   USE(zn);
9349   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9350   VIXL_ASSERT(zd.Is(zn));
9351   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9352 
9353   Emit(0x440b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9354 }
9355 
uqrshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9356 void Assembler::uqrshlr(const ZRegister& zd,
9357                         const PRegisterM& pg,
9358                         const ZRegister& zn,
9359                         const ZRegister& zm) {
9360   // UQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9361   //  0100 0100 ..00 1111 100. .... .... ....
9362   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9363   //  Zdn<4:0>
9364 
9365   USE(zn);
9366   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9367   VIXL_ASSERT(zd.Is(zn));
9368   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9369 
9370   Emit(0x440f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9371 }
9372 
uqshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)9373 void Assembler::uqshl(const ZRegister& zd,
9374                       const PRegisterM& pg,
9375                       const ZRegister& zn,
9376                       int shift) {
9377   // UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
9378   //  0000 0100 ..00 0111 100. .... .... ....
9379   //  tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
9380   //  imm3<7:5> | Zdn<4:0>
9381 
9382   USE(zn);
9383   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9384   VIXL_ASSERT(zd.Is(zn));
9385   Instr encoded_imm =
9386       EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
9387   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04078000);
9388 }
9389 
uqshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9390 void Assembler::uqshl(const ZRegister& zd,
9391                       const PRegisterM& pg,
9392                       const ZRegister& zn,
9393                       const ZRegister& zm) {
9394   // UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9395   //  0100 0100 ..00 1001 100. .... .... ....
9396   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9397   //  Zdn<4:0>
9398 
9399   USE(zn);
9400   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9401   VIXL_ASSERT(zd.Is(zn));
9402   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9403 
9404   Emit(0x44098000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9405 }
9406 
uqshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9407 void Assembler::uqshlr(const ZRegister& zd,
9408                        const PRegisterM& pg,
9409                        const ZRegister& zn,
9410                        const ZRegister& zm) {
9411   // UQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9412   //  0100 0100 ..00 1101 100. .... .... ....
9413   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9414   //  Zdn<4:0>
9415 
9416   USE(zn);
9417   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9418   VIXL_ASSERT(zd.Is(zn));
9419   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9420 
9421   Emit(0x440d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9422 }
9423 
uqsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9424 void Assembler::uqsub(const ZRegister& zd,
9425                       const PRegisterM& pg,
9426                       const ZRegister& zn,
9427                       const ZRegister& zm) {
9428   // UQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9429   //  0100 0100 ..01 1011 100. .... .... ....
9430   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9431 
9432   USE(zn);
9433   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9434   VIXL_ASSERT(zd.Is(zn));
9435   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9436 
9437   Emit(0x441b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9438 }
9439 
uqsubr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9440 void Assembler::uqsubr(const ZRegister& zd,
9441                        const PRegisterM& pg,
9442                        const ZRegister& zn,
9443                        const ZRegister& zm) {
9444   // UQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9445   //  0100 0100 ..01 1111 100. .... .... ....
9446   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9447 
9448   USE(zn);
9449   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9450   VIXL_ASSERT(zd.Is(zn));
9451   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9452 
9453   Emit(0x441f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9454 }
9455 
uqxtnb(const ZRegister & zd,const ZRegister & zn)9456 void Assembler::uqxtnb(const ZRegister& zd, const ZRegister& zn) {
9457   // UQXTNB <Zd>.<T>, <Zn>.<Tb>
9458   //  0100 0101 0.1. .000 0100 10.. .... ....
9459   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
9460 
9461   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9462   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
9463   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
9464 
9465   // XTN instructions look like immediate shifts with zero shift distance.
9466   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
9467   SVEBitwiseShiftImmediate(zd, zn, size, 0x45204800);
9468 }
9469 
uqxtnt(const ZRegister & zd,const ZRegister & zn)9470 void Assembler::uqxtnt(const ZRegister& zd, const ZRegister& zn) {
9471   // UQXTNT <Zd>.<T>, <Zn>.<Tb>
9472   //  0100 0101 0.1. .000 0100 11.. .... ....
9473   //  tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
9474 
9475   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9476   VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
9477   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
9478 
9479   // XTN instructions look like immediate shifts with zero shift distance.
9480   Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
9481   SVEBitwiseShiftImmediate(zd, zn, size, 0x45204c00);
9482 }
9483 
urecpe(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)9484 void Assembler::urecpe(const ZRegister& zd,
9485                        const PRegisterM& pg,
9486                        const ZRegister& zn) {
9487   // URECPE <Zd>.S, <Pg>/M, <Zn>.S
9488   //  0100 0100 ..00 0000 101. .... .... ....
9489   //  size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
9490 
9491   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9492   VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());
9493 
9494   Emit(0x4400a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
9495 }
9496 
urhadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9497 void Assembler::urhadd(const ZRegister& zd,
9498                        const PRegisterM& pg,
9499                        const ZRegister& zn,
9500                        const ZRegister& zm) {
9501   // URHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9502   //  0100 0100 ..01 0101 100. .... .... ....
9503   //  size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9504 
9505   USE(zn);
9506   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9507   VIXL_ASSERT(zd.Is(zn));
9508   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9509 
9510   Emit(0x44158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9511 }
9512 
urshl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9513 void Assembler::urshl(const ZRegister& zd,
9514                       const PRegisterM& pg,
9515                       const ZRegister& zn,
9516                       const ZRegister& zm) {
9517   // URSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9518   //  0100 0100 ..00 0011 100. .... .... ....
9519   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9520   //  Zdn<4:0>
9521 
9522   USE(zn);
9523   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9524   VIXL_ASSERT(zd.Is(zn));
9525   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9526 
9527   Emit(0x44038000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9528 }
9529 
urshlr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9530 void Assembler::urshlr(const ZRegister& zd,
9531                        const PRegisterM& pg,
9532                        const ZRegister& zn,
9533                        const ZRegister& zm) {
9534   // URSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9535   //  0100 0100 ..00 0111 100. .... .... ....
9536   //  size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9537   //  Zdn<4:0>
9538 
9539   USE(zn);
9540   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9541   VIXL_ASSERT(zd.Is(zn));
9542   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9543 
9544   Emit(0x44078000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9545 }
9546 
urshr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)9547 void Assembler::urshr(const ZRegister& zd,
9548                       const PRegisterM& pg,
9549                       const ZRegister& zn,
9550                       int shift) {
9551   // URSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
9552   //  0000 0100 ..00 1101 100. .... .... ....
9553   //  tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
9554   //  imm3<7:5> | Zdn<4:0>
9555 
9556   USE(zn);
9557   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9558   VIXL_ASSERT(zd.Is(zn));
9559   Instr encoded_imm =
9560       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
9561   SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040d8000);
9562 }
9563 
ursqrte(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)9564 void Assembler::ursqrte(const ZRegister& zd,
9565                         const PRegisterM& pg,
9566                         const ZRegister& zn) {
9567   // URSQRTE <Zd>.S, <Pg>/M, <Zn>.S
9568   //  0100 0100 ..00 0001 101. .... .... ....
9569   //  size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
9570 
9571   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9572   VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());
9573 
9574   Emit(0x4401a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
9575 }
9576 
ursra(const ZRegister & zda,const ZRegister & zn,int shift)9577 void Assembler::ursra(const ZRegister& zda, const ZRegister& zn, int shift) {
9578   // URSRA <Zda>.<T>, <Zn>.<T>, #<const>
9579   //  0100 0101 ..0. .... 1110 11.. .... ....
9580   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
9581   //  Zda<4:0>
9582 
9583   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9584   VIXL_ASSERT(AreSameLaneSize(zda, zn));
9585   Instr encoded_imm =
9586       EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
9587 
9588   SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500ec00);
9589 }
9590 
ushllb(const ZRegister & zd,const ZRegister & zn,int shift)9591 void Assembler::ushllb(const ZRegister& zd, const ZRegister& zn, int shift) {
9592   // USHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>
9593   //  0100 0101 0.0. .... 1010 10.. .... ....
9594   //  tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9595 
9596   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9597   VIXL_ASSERT(!zd.IsLaneSizeB());
9598   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9599 
9600   Instr encoded_imm =
9601       EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
9602   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a800);
9603 }
9604 
ushllt(const ZRegister & zd,const ZRegister & zn,int shift)9605 void Assembler::ushllt(const ZRegister& zd, const ZRegister& zn, int shift) {
9606   // USHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>
9607   //  0100 0101 0.0. .... 1010 11.. .... ....
9608   //  tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9609 
9610   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9611   VIXL_ASSERT(!zd.IsLaneSizeB());
9612   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9613 
9614   Instr encoded_imm =
9615       EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
9616   SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500ac00);
9617 }
9618 
usqadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm)9619 void Assembler::usqadd(const ZRegister& zd,
9620                        const PRegisterM& pg,
9621                        const ZRegister& zn,
9622                        const ZRegister& zm) {
9623   // USQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9624   //  0100 0100 ..01 1101 100. .... .... ....
9625   //  size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9626 
9627   USE(zn);
9628   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9629   VIXL_ASSERT(zd.Is(zn));
9630   VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9631 
9632   Emit(0x441d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9633 }
9634 
usra(const ZRegister & zda,const ZRegister & zn,int shift)9635 void Assembler::usra(const ZRegister& zda, const ZRegister& zn, int shift) {
9636   // USRA <Zda>.<T>, <Zn>.<T>, #<const>
9637   //  0100 0101 ..0. .... 1110 01.. .... ....
9638   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
9639   //  Zda<4:0>
9640 
9641   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9642   VIXL_ASSERT(AreSameLaneSize(zda, zn));
9643   Instr encoded_imm =
9644       EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
9645 
9646   SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e400);
9647 }
9648 
usublb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9649 void Assembler::usublb(const ZRegister& zd,
9650                        const ZRegister& zn,
9651                        const ZRegister& zm) {
9652   // USUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9653   //  0100 0101 ..0. .... 0001 10.. .... ....
9654   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9655   //  Zd<4:0>
9656 
9657   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9658   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9659   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9660   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9661 
9662   Emit(0x45001800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9663 }
9664 
usublt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9665 void Assembler::usublt(const ZRegister& zd,
9666                        const ZRegister& zn,
9667                        const ZRegister& zm) {
9668   // USUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9669   //  0100 0101 ..0. .... 0001 11.. .... ....
9670   //  size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9671   //  Zd<4:0>
9672 
9673   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9674   VIXL_ASSERT(AreSameLaneSize(zn, zm));
9675   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9676   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9677 
9678   Emit(0x45001c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9679 }
9680 
usubwb(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9681 void Assembler::usubwb(const ZRegister& zd,
9682                        const ZRegister& zn,
9683                        const ZRegister& zm) {
9684   // USUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9685   //  0100 0101 ..0. .... 0101 10.. .... ....
9686   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9687 
9688   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9689   VIXL_ASSERT(AreSameLaneSize(zd, zn));
9690   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9691   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9692 
9693   Emit(0x45005800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9694 }
9695 
usubwt(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)9696 void Assembler::usubwt(const ZRegister& zd,
9697                        const ZRegister& zn,
9698                        const ZRegister& zm) {
9699   // USUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9700   //  0100 0101 ..0. .... 0101 11.. .... ....
9701   //  size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9702 
9703   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9704   VIXL_ASSERT(AreSameLaneSize(zd, zn));
9705   VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9706   VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9707 
9708   Emit(0x45005c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9709 }
9710 
whilege(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9711 void Assembler::whilege(const PRegisterWithLaneSize& pd,
9712                         const Register& rn,
9713                         const Register& rm) {
9714   // WHILEGE <Pd>.<T>, <R><n>, <R><m>
9715   //  0010 0101 ..1. .... 000. 00.. ...0 ....
9716   //  size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9717   //  Pd<3:0>
9718 
9719   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9720   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9721   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9722 
9723   Emit(0x25200000 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9724 }
9725 
whilegt(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9726 void Assembler::whilegt(const PRegisterWithLaneSize& pd,
9727                         const Register& rn,
9728                         const Register& rm) {
9729   // WHILEGT <Pd>.<T>, <R><n>, <R><m>
9730   //  0010 0101 ..1. .... 000. 00.. ...1 ....
9731   //  size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9732   //  Pd<3:0>
9733 
9734   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9735   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9736   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9737 
9738   Emit(0x25200010 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9739 }
9740 
whilehi(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9741 void Assembler::whilehi(const PRegisterWithLaneSize& pd,
9742                         const Register& rn,
9743                         const Register& rm) {
9744   // WHILEHI <Pd>.<T>, <R><n>, <R><m>
9745   //  0010 0101 ..1. .... 000. 10.. ...1 ....
9746   //  size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9747   //  Pd<3:0>
9748 
9749   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9750   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9751   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9752 
9753   Emit(0x25200810 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9754 }
9755 
whilehs(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9756 void Assembler::whilehs(const PRegisterWithLaneSize& pd,
9757                         const Register& rn,
9758                         const Register& rm) {
9759   // WHILEHS <Pd>.<T>, <R><n>, <R><m>
9760   //  0010 0101 ..1. .... 000. 10.. ...0 ....
9761   //  size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9762   //  Pd<3:0>
9763 
9764   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9765   VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9766   const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9767 
9768   Emit(0x25200800 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9769 }
9770 
whilerw(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9771 void Assembler::whilerw(const PRegisterWithLaneSize& pd,
9772                         const Register& rn,
9773                         const Register& rm) {
9774   // WHILERW <Pd>.<T>, <Xn>, <Xm>
9775   //  0010 0101 ..1. .... 0011 00.. ...1 ....
9776   //  size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>
9777 
9778   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9779   VIXL_ASSERT(rn.IsX() && rm.IsX());
9780 
9781   Emit(0x25203010 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));
9782 }
9783 
whilewr(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)9784 void Assembler::whilewr(const PRegisterWithLaneSize& pd,
9785                         const Register& rn,
9786                         const Register& rm) {
9787   // WHILEWR <Pd>.<T>, <Xn>, <Xm>
9788   //  0010 0101 ..1. .... 0011 00.. ...0 ....
9789   //  size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>
9790 
9791   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9792   VIXL_ASSERT(rn.IsX() && rm.IsX());
9793 
9794   Emit(0x25203000 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));
9795 }
9796 
xar(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,int shift)9797 void Assembler::xar(const ZRegister& zd,
9798                     const ZRegister& zn,
9799                     const ZRegister& zm,
9800                     int shift) {
9801   // XAR <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<const>
9802   //  0000 0100 ..1. .... 0011 01.. .... ....
9803   //  tszh<23:22> | tszl<20:19> | imm3<18:16> | Zm<9:5> | Zdn<4:0>
9804 
9805   USE(zn);
9806   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9807   VIXL_ASSERT(zd.Is(zn));
9808   VIXL_ASSERT(AreSameLaneSize(zd, zm));
9809 
9810   Instr encoded_imm =
9811       EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
9812   SVEBitwiseShiftImmediate(zd, zm, encoded_imm, 0x04203400);
9813 }
9814 
fmmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9815 void Assembler::fmmla(const ZRegister& zda,
9816                       const ZRegister& zn,
9817                       const ZRegister& zm) {
9818   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9819   VIXL_ASSERT((CPUHas(CPUFeatures::kSVEF32MM) && zda.IsLaneSizeS()) ||
9820               (CPUHas(CPUFeatures::kSVEF64MM) && zda.IsLaneSizeD()));
9821   VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
9822 
9823   Emit(0x6420e400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9824 }
9825 
smmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9826 void Assembler::smmla(const ZRegister& zda,
9827                       const ZRegister& zn,
9828                       const ZRegister& zm) {
9829   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9830   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9831   VIXL_ASSERT(zda.IsLaneSizeS());
9832   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9833 
9834   Emit(0x45009800 | Rd(zda) | Rn(zn) | Rm(zm));
9835 }
9836 
usmmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9837 void Assembler::usmmla(const ZRegister& zda,
9838                        const ZRegister& zn,
9839                        const ZRegister& zm) {
9840   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9841   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9842   VIXL_ASSERT(zda.IsLaneSizeS());
9843   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9844 
9845   Emit(0x45809800 | Rd(zda) | Rn(zn) | Rm(zm));
9846 }
9847 
ummla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9848 void Assembler::ummla(const ZRegister& zda,
9849                       const ZRegister& zn,
9850                       const ZRegister& zm) {
9851   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9852   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9853   VIXL_ASSERT(zda.IsLaneSizeS());
9854   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9855 
9856   Emit(0x45c09800 | Rd(zda) | Rn(zn) | Rm(zm));
9857 }
9858 
usdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm)9859 void Assembler::usdot(const ZRegister& zda,
9860                       const ZRegister& zn,
9861                       const ZRegister& zm) {
9862   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9863   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9864   VIXL_ASSERT(zda.IsLaneSizeS());
9865   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9866 
9867   Emit(0x44807800 | Rd(zda) | Rn(zn) | Rm(zm));
9868 }
9869 
usdot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)9870 void Assembler::usdot(const ZRegister& zda,
9871                       const ZRegister& zn,
9872                       const ZRegister& zm,
9873                       int index) {
9874   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9875   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9876   VIXL_ASSERT(zda.IsLaneSizeS());
9877   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9878   VIXL_ASSERT(zm.GetCode() <= 7);
9879   VIXL_ASSERT(IsUint2(index));
9880 
9881   Emit(0x44a01800 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));
9882 }
9883 
sudot(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index)9884 void Assembler::sudot(const ZRegister& zda,
9885                       const ZRegister& zn,
9886                       const ZRegister& zm,
9887                       int index) {
9888   VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9889   VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9890   VIXL_ASSERT(zda.IsLaneSizeS());
9891   VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9892   VIXL_ASSERT(zm.GetCode() <= 7);
9893   VIXL_ASSERT(IsUint2(index));
9894 
9895   Emit(0x44a01c00 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));
9896 }
9897 
9898 }  // namespace aarch64
9899 }  // namespace vixl
9900