1 // Copyright 2015, 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 "instructions-aarch64.h"
28 #include "assembler-aarch64.h"
29 
30 namespace vixl {
31 namespace aarch64 {
32 
RepeatBitsAcrossReg(unsigned reg_size,uint64_t value,unsigned width)33 static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
34                                     uint64_t value,
35                                     unsigned width) {
36   VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
37               (width == 32));
38   VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
39               (reg_size == kSRegSize) || (reg_size == kDRegSize));
40   uint64_t result = value & ((UINT64_C(1) << width) - 1);
41   for (unsigned i = width; i < reg_size; i *= 2) {
42     result |= (result << i);
43   }
44   return result;
45 }
46 
CanTakeSVEMovprfx(const Instruction * movprfx) const47 bool Instruction::CanTakeSVEMovprfx(const Instruction* movprfx) const {
48   bool movprfx_is_predicated = movprfx->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z;
49   bool movprfx_is_unpredicated =
50       movprfx->Mask(SVEConstructivePrefix_UnpredicatedMask) == MOVPRFX_z_z;
51   VIXL_ASSERT(movprfx_is_predicated != movprfx_is_unpredicated);
52 
53   int movprfx_zd = movprfx->GetRd();
54   int movprfx_pg = movprfx_is_predicated ? movprfx->GetPgLow8() : -1;
55   VectorFormat movprfx_vform =
56       movprfx_is_predicated ? movprfx->GetSVEVectorFormat() : kFormatUndefined;
57 
58   bool pg_matches_low8 = movprfx_pg == GetPgLow8();
59   bool vform_matches = movprfx_vform == GetSVEVectorFormat();
60   bool zd_matches = movprfx_zd == GetRd();
61   bool zd_matches_zm = movprfx_zd == GetRm();
62   bool zd_matches_zn = movprfx_zd == GetRn();
63 
64   switch (Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask)) {
65     case AND_z_zi:
66     case EOR_z_zi:
67     case ORR_z_zi:
68       return movprfx_is_unpredicated && zd_matches;
69   }
70   switch (Mask(SVEBitwiseLogical_PredicatedMask)) {
71     case AND_z_p_zz:
72     case BIC_z_p_zz:
73     case EOR_z_p_zz:
74     case ORR_z_p_zz:
75       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
76         return false;
77       }
78       // The movprfx's `zd` must not alias any other inputs.
79       if (movprfx_zd == GetRx<9, 5>()) return false;
80       return zd_matches;
81   }
82   switch (Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
83     case ASRD_z_p_zi:
84     case ASR_z_p_zi:
85     case LSL_z_p_zi:
86     case LSR_z_p_zi:
87       if (movprfx_is_predicated) {
88         if (!pg_matches_low8) return false;
89         unsigned tsz = ExtractBits<0x00c00300>();
90         VectorFormat instr_vform =
91             SVEFormatFromLaneSizeInBytesLog2(HighestSetBitPosition(tsz));
92         if (movprfx_vform != instr_vform) return false;
93       }
94       return zd_matches;
95   }
96   switch (Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
97     case ASRR_z_p_zz:
98     case ASR_z_p_zz:
99     case LSLR_z_p_zz:
100     case LSL_z_p_zz:
101     case LSRR_z_p_zz:
102     case LSR_z_p_zz:
103       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
104         return false;
105       }
106       // The movprfx's `zd` must not alias any other inputs.
107       if (movprfx_zd == GetRx<9, 5>()) return false;
108       return zd_matches;
109   }
110   switch (Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
111     case ASR_z_p_zw:
112     case LSL_z_p_zw:
113     case LSR_z_p_zw:
114       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
115         return false;
116       }
117       // The movprfx's `zd` must not alias any other inputs.
118       if (movprfx_zd == GetRx<9, 5>()) return false;
119       return zd_matches;
120   }
121   switch (Mask(SVEConditionallyBroadcastElementToVectorMask)) {
122     case CLASTA_z_p_zz:
123     case CLASTB_z_p_zz:
124       // The movprfx's `zd` must not alias any other inputs.
125       if (movprfx_zd == GetRx<9, 5>()) return false;
126       return movprfx_is_unpredicated && zd_matches;
127   }
128   switch (Mask(SVECopyFPImm_PredicatedMask)) {
129     case FCPY_z_p_i:
130       if (movprfx_is_predicated) {
131         if (!vform_matches) return false;
132         if (movprfx_pg != GetRx<19, 16>()) return false;
133       }
134       return zd_matches;
135   }
136   switch (Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
137     case CPY_z_p_r:
138       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
139         return false;
140       }
141       return zd_matches;
142   }
143   switch (Mask(SVECopyIntImm_PredicatedMask)) {
144     case CPY_z_p_i:
145       if (movprfx_is_predicated) {
146         if (!vform_matches) return false;
147         if (movprfx_pg != GetRx<19, 16>()) return false;
148       }
149       // Only the merging form can take movprfx.
150       if (ExtractBit(14) == 0) return false;
151       return zd_matches;
152   }
153   switch (Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
154     case CPY_z_p_v:
155       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
156         return false;
157       }
158       return zd_matches && !zd_matches_zn;
159   }
160   switch (Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
161     case FADD_z_p_zs:
162     case FMAXNM_z_p_zs:
163     case FMAX_z_p_zs:
164     case FMINNM_z_p_zs:
165     case FMIN_z_p_zs:
166     case FMUL_z_p_zs:
167     case FSUBR_z_p_zs:
168     case FSUB_z_p_zs:
169       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
170         return false;
171       }
172       return zd_matches;
173   }
174   switch (Mask(SVEFPArithmetic_PredicatedMask)) {
175     case FABD_z_p_zz:
176     case FADD_z_p_zz:
177     case FDIVR_z_p_zz:
178     case FDIV_z_p_zz:
179     case FMAXNM_z_p_zz:
180     case FMAX_z_p_zz:
181     case FMINNM_z_p_zz:
182     case FMIN_z_p_zz:
183     case FMULX_z_p_zz:
184     case FMUL_z_p_zz:
185     case FSCALE_z_p_zz:
186     case FSUBR_z_p_zz:
187     case FSUB_z_p_zz:
188       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
189         return false;
190       }
191       // The movprfx's `zd` must not alias any other inputs.
192       if (movprfx_zd == GetRx<9, 5>()) return false;
193       return zd_matches;
194   }
195   switch (Mask(SVEFPComplexAdditionMask)) {
196     case FCADD_z_p_zz:
197       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
198         return false;
199       }
200       // The movprfx's `zd` must not alias any other inputs.
201       if (movprfx_zd == GetRx<9, 5>()) return false;
202       return zd_matches;
203   }
204   switch (Mask(SVEFPComplexMulAddIndexMask)) {
205     case FCMLA_z_zzzi_h:
206       // The movprfx's `zd` must not alias any other inputs.
207       if (movprfx_zd == GetRx<18, 16>()) return false;
208       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
209     case FCMLA_z_zzzi_s:
210       // The movprfx's `zd` must not alias any other inputs.
211       if (movprfx_zd == GetRx<19, 16>()) return false;
212       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
213   }
214   switch (Mask(SVEFPComplexMulAddMask)) {
215     case FCMLA_z_p_zzz:
216       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
217         return false;
218       }
219       return zd_matches && !zd_matches_zm && !zd_matches_zn;
220   }
221   switch (Mask(SVEFPConvertPrecisionMask)) {
222     case FCVT_z_p_z_d2h:
223     case FCVT_z_p_z_d2s:
224     case FCVT_z_p_z_h2d:
225     case FCVT_z_p_z_h2s:
226     case FCVT_z_p_z_s2d:
227     case FCVT_z_p_z_s2h:
228       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
229         return false;
230       }
231       return zd_matches && !zd_matches_zn;
232   }
233   switch (Mask(SVEFPConvertToIntMask)) {
234     case FCVTZS_z_p_z_d2w:
235     case FCVTZS_z_p_z_d2x:
236     case FCVTZS_z_p_z_fp162h:
237     case FCVTZS_z_p_z_fp162w:
238     case FCVTZS_z_p_z_fp162x:
239     case FCVTZS_z_p_z_s2w:
240     case FCVTZS_z_p_z_s2x:
241     case FCVTZU_z_p_z_d2w:
242     case FCVTZU_z_p_z_d2x:
243     case FCVTZU_z_p_z_fp162h:
244     case FCVTZU_z_p_z_fp162w:
245     case FCVTZU_z_p_z_fp162x:
246     case FCVTZU_z_p_z_s2w:
247     case FCVTZU_z_p_z_s2x:
248       if (movprfx_is_predicated) {
249         if (!pg_matches_low8) return false;
250         // The movprfx element size must match the instruction's maximum encoded
251         // element size. We have to partially decode the opc and opc2 fields to
252         // find this.
253         unsigned opc = ExtractBits(23, 22);
254         unsigned opc2 = ExtractBits(18, 17);
255         VectorFormat instr_vform =
256             SVEFormatFromLaneSizeInBytesLog2(std::max(opc, opc2));
257         if (movprfx_vform != instr_vform) return false;
258       }
259       return zd_matches && !zd_matches_zn;
260   }
261   switch (Mask(SVEFPMulAddIndexMask)) {
262     case FMLA_z_zzzi_h:
263     case FMLA_z_zzzi_h_i3h:
264     case FMLA_z_zzzi_s:
265     case FMLS_z_zzzi_h:
266     case FMLS_z_zzzi_h_i3h:
267     case FMLS_z_zzzi_s:
268       // The movprfx's `zd` must not alias any other inputs.
269       if (movprfx_zd == GetRx<18, 16>()) return false;
270       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
271     case FMLA_z_zzzi_d:
272     case FMLS_z_zzzi_d:
273       // The movprfx's `zd` must not alias any other inputs.
274       if (movprfx_zd == GetRx<19, 16>()) return false;
275       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
276   }
277   switch (Mask(SVEFPMulAddMask)) {
278     case FMAD_z_p_zzz:
279     case FMSB_z_p_zzz:
280     case FNMAD_z_p_zzz:
281     case FNMSB_z_p_zzz:
282       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
283         return false;
284       }
285       // The movprfx's `zd` must not alias any other inputs.
286       if (movprfx_zd == GetRx<20, 16>()) return false;
287       if (movprfx_zd == GetRx<9, 5>()) return false;
288       return zd_matches;
289     case FMLA_z_p_zzz:
290     case FMLS_z_p_zzz:
291     case FNMLA_z_p_zzz:
292     case FNMLS_z_p_zzz:
293       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
294         return false;
295       }
296       return zd_matches && !zd_matches_zm && !zd_matches_zn;
297   }
298   switch (Mask(SVEFPRoundToIntegralValueMask)) {
299     case FRINTA_z_p_z:
300     case FRINTI_z_p_z:
301     case FRINTM_z_p_z:
302     case FRINTN_z_p_z:
303     case FRINTP_z_p_z:
304     case FRINTX_z_p_z:
305     case FRINTZ_z_p_z:
306       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
307         return false;
308       }
309       return zd_matches && !zd_matches_zn;
310   }
311   switch (Mask(SVEFPTrigMulAddCoefficientMask)) {
312     case FTMAD_z_zzi:
313       // The movprfx's `zd` must not alias any other inputs.
314       if (movprfx_zd == GetRx<9, 5>()) return false;
315       return movprfx_is_unpredicated && zd_matches;
316   }
317   switch (Mask(SVEFPUnaryOpMask)) {
318     case FRECPX_z_p_z:
319     case FSQRT_z_p_z:
320       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
321         return false;
322       }
323       return zd_matches && !zd_matches_zn;
324   }
325   switch (Mask(SVEIncDecByPredicateCountMask)) {
326     case DECP_z_p_z:
327     case INCP_z_p_z:
328     case SQDECP_z_p_z:
329     case SQINCP_z_p_z:
330     case UQDECP_z_p_z:
331     case UQINCP_z_p_z:
332       return movprfx_is_unpredicated && zd_matches;
333   }
334   switch (Mask(SVEIncDecVectorByElementCountMask)) {
335     case DECD_z_zs:
336     case DECH_z_zs:
337     case DECW_z_zs:
338     case INCD_z_zs:
339     case INCH_z_zs:
340     case INCW_z_zs:
341       return movprfx_is_unpredicated && zd_matches;
342   }
343   switch (Mask(SVEInsertGeneralRegisterMask)) {
344     case INSR_z_r:
345       return movprfx_is_unpredicated && zd_matches;
346   }
347   switch (Mask(SVEInsertSIMDFPScalarRegisterMask)) {
348     case INSR_z_v:
349       // The movprfx's `zd` must not alias any other inputs.
350       if (movprfx_zd == GetRx<9, 5>()) return false;
351       return movprfx_is_unpredicated && zd_matches;
352   }
353   switch (Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
354     case ADD_z_zi:
355     case SQADD_z_zi:
356     case SQSUB_z_zi:
357     case SUBR_z_zi:
358     case SUB_z_zi:
359     case UQADD_z_zi:
360     case UQSUB_z_zi:
361       return movprfx_is_unpredicated && zd_matches;
362   }
363   switch (Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
364     case ADD_z_p_zz:
365     case SUBR_z_p_zz:
366     case SUB_z_p_zz:
367       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
368         return false;
369       }
370       // The movprfx's `zd` must not alias any other inputs.
371       if (movprfx_zd == GetRx<9, 5>()) return false;
372       return zd_matches;
373   }
374   switch (Mask(SVEIntConvertToFPMask)) {
375     case SCVTF_z_p_z_h2fp16:
376     case SCVTF_z_p_z_w2d:
377     case SCVTF_z_p_z_w2fp16:
378     case SCVTF_z_p_z_w2s:
379     case SCVTF_z_p_z_x2d:
380     case SCVTF_z_p_z_x2fp16:
381     case SCVTF_z_p_z_x2s:
382     case UCVTF_z_p_z_h2fp16:
383     case UCVTF_z_p_z_w2d:
384     case UCVTF_z_p_z_w2fp16:
385     case UCVTF_z_p_z_w2s:
386     case UCVTF_z_p_z_x2d:
387     case UCVTF_z_p_z_x2fp16:
388     case UCVTF_z_p_z_x2s:
389       if (movprfx_is_predicated) {
390         if (!pg_matches_low8) return false;
391         // The movprfx element size must match the instruction's maximum encoded
392         // element size. We have to partially decode the opc and opc2 fields to
393         // find this.
394         unsigned opc = ExtractBits(23, 22);
395         unsigned opc2 = ExtractBits(18, 17);
396         VectorFormat instr_vform =
397             SVEFormatFromLaneSizeInBytesLog2(std::max(opc, opc2));
398         if (movprfx_vform != instr_vform) return false;
399       }
400       return zd_matches && !zd_matches_zn;
401   }
402   switch (Mask(SVEIntDivideVectors_PredicatedMask)) {
403     case SDIVR_z_p_zz:
404     case SDIV_z_p_zz:
405     case UDIVR_z_p_zz:
406     case UDIV_z_p_zz:
407       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
408         return false;
409       }
410       // The movprfx's `zd` must not alias any other inputs.
411       if (movprfx_zd == GetRx<9, 5>()) return false;
412       return zd_matches;
413   }
414   switch (Mask(SVEIntMinMaxDifference_PredicatedMask)) {
415     case SABD_z_p_zz:
416     case SMAX_z_p_zz:
417     case SMIN_z_p_zz:
418     case UABD_z_p_zz:
419     case UMAX_z_p_zz:
420     case UMIN_z_p_zz:
421       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
422         return false;
423       }
424       // The movprfx's `zd` must not alias any other inputs.
425       if (movprfx_zd == GetRx<9, 5>()) return false;
426       return zd_matches;
427   }
428   switch (Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
429     case SMAX_z_zi:
430     case SMIN_z_zi:
431     case UMAX_z_zi:
432     case UMIN_z_zi:
433       return movprfx_is_unpredicated && zd_matches;
434   }
435   switch (Mask(SVEIntMulAddPredicatedMask)) {
436     case MAD_z_p_zzz:
437     case MSB_z_p_zzz:
438       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
439         return false;
440       }
441       // The movprfx's `zd` must not alias any other inputs.
442       if (movprfx_zd == GetRx<9, 5>()) return false;
443       return zd_matches && !zd_matches_zm;
444     case MLA_z_p_zzz:
445     case MLS_z_p_zzz:
446       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
447         return false;
448       }
449       return zd_matches && !zd_matches_zm && !zd_matches_zn;
450   }
451   switch (Mask(SVEIntMulAddUnpredicatedMask)) {
452     case SDOT_z_zzz:
453     case UDOT_z_zzz:
454       return movprfx_is_unpredicated && zd_matches && !zd_matches_zm &&
455              !zd_matches_zn;
456   }
457   switch (Mask(SVEIntMulImm_UnpredicatedMask)) {
458     case MUL_z_zi:
459       return movprfx_is_unpredicated && zd_matches;
460   }
461   switch (Mask(SVEIntMulVectors_PredicatedMask)) {
462     case MUL_z_p_zz:
463     case SMULH_z_p_zz:
464     case UMULH_z_p_zz:
465       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
466         return false;
467       }
468       // The movprfx's `zd` must not alias any other inputs.
469       if (movprfx_zd == GetRx<9, 5>()) return false;
470       return zd_matches;
471   }
472   switch (Mask(SVEIntUnaryArithmeticPredicatedMask)) {
473     case ABS_z_p_z:
474     case CLS_z_p_z:
475     case CLZ_z_p_z:
476     case CNOT_z_p_z:
477     case CNT_z_p_z:
478     case FABS_z_p_z:
479     case FNEG_z_p_z:
480     case NEG_z_p_z:
481     case NOT_z_p_z:
482     case SXTB_z_p_z:
483     case SXTH_z_p_z:
484     case SXTW_z_p_z:
485     case UXTB_z_p_z:
486     case UXTH_z_p_z:
487     case UXTW_z_p_z:
488       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
489         return false;
490       }
491       return zd_matches && !zd_matches_zn;
492   }
493   switch (Mask(SVEMulIndexMask)) {
494     case SDOT_z_zzzi_s:
495     case UDOT_z_zzzi_s:
496       // The movprfx's `zd` must not alias any other inputs.
497       if (movprfx_zd == GetRx<18, 16>()) return false;
498       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
499     case SDOT_z_zzzi_d:
500     case UDOT_z_zzzi_d:
501       // The movprfx's `zd` must not alias any other inputs.
502       if (movprfx_zd == GetRx<19, 16>()) return false;
503       return movprfx_is_unpredicated && zd_matches && !zd_matches_zn;
504   }
505   switch (Mask(SVEPermuteVectorExtractMask)) {
506     case EXT_z_zi_des:
507       // The movprfx's `zd` must not alias any other inputs.
508       if (movprfx_zd == GetRx<9, 5>()) return false;
509       return movprfx_is_unpredicated && zd_matches;
510   }
511   switch (Mask(SVEReverseWithinElementsMask)) {
512     case RBIT_z_p_z:
513     case REVB_z_z:
514     case REVH_z_z:
515     case REVW_z_z:
516       if (movprfx_is_predicated && !(pg_matches_low8 && vform_matches)) {
517         return false;
518       }
519       return zd_matches && !zd_matches_zn;
520   }
521   switch (Mask(SVESaturatingIncDecVectorByElementCountMask)) {
522     case SQDECD_z_zs:
523     case SQDECH_z_zs:
524     case SQDECW_z_zs:
525     case SQINCD_z_zs:
526     case SQINCH_z_zs:
527     case SQINCW_z_zs:
528     case UQDECD_z_zs:
529     case UQDECH_z_zs:
530     case UQDECW_z_zs:
531     case UQINCD_z_zs:
532     case UQINCH_z_zs:
533     case UQINCW_z_zs:
534       return movprfx_is_unpredicated && zd_matches;
535   }
536   switch (Mask(SVEVectorSplice_DestructiveMask)) {
537     case SPLICE_z_p_zz_des:
538       // The movprfx's `zd` must not alias any other inputs.
539       if (movprfx_zd == GetRx<9, 5>()) return false;
540       return movprfx_is_unpredicated && zd_matches;
541   }
542   return false;
543 }  // NOLINT(readability/fn_size)
544 
IsLoad() const545 bool Instruction::IsLoad() const {
546   if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
547     return false;
548   }
549 
550   if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
551     return Mask(LoadStorePairLBit) != 0;
552   } else {
553     LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
554     switch (op) {
555       case LDRB_w:
556       case LDRH_w:
557       case LDR_w:
558       case LDR_x:
559       case LDRSB_w:
560       case LDRSB_x:
561       case LDRSH_w:
562       case LDRSH_x:
563       case LDRSW_x:
564       case LDR_b:
565       case LDR_h:
566       case LDR_s:
567       case LDR_d:
568       case LDR_q:
569         return true;
570       default:
571         return false;
572     }
573   }
574 }
575 
576 
IsStore() const577 bool Instruction::IsStore() const {
578   if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
579     return false;
580   }
581 
582   if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
583     return Mask(LoadStorePairLBit) == 0;
584   } else {
585     LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
586     switch (op) {
587       case STRB_w:
588       case STRH_w:
589       case STR_w:
590       case STR_x:
591       case STR_b:
592       case STR_h:
593       case STR_s:
594       case STR_d:
595       case STR_q:
596         return true;
597       default:
598         return false;
599     }
600   }
601 }
602 
603 
GetSVEPermuteIndexAndLaneSizeLog2() const604 std::pair<int, int> Instruction::GetSVEPermuteIndexAndLaneSizeLog2() const {
605   uint32_t imm_2 = ExtractBits<0x00C00000>();
606   uint32_t tsz_5 = ExtractBits<0x001F0000>();
607   uint32_t imm_7 = (imm_2 << 5) | tsz_5;
608   int lane_size_in_byte_log_2 = std::min(CountTrailingZeros(tsz_5), 5);
609   int index = ExtractUnsignedBitfield32(6, lane_size_in_byte_log_2 + 1, imm_7);
610   return std::make_pair(index, lane_size_in_byte_log_2);
611 }
612 
613 
614 // Logical immediates can't encode zero, so a return value of zero is used to
615 // indicate a failure case. Specifically, where the constraints on imm_s are
616 // not met.
GetImmLogical() const617 uint64_t Instruction::GetImmLogical() const {
618   unsigned reg_size = GetSixtyFourBits() ? kXRegSize : kWRegSize;
619   int32_t n = GetBitN();
620   int32_t imm_s = GetImmSetBits();
621   int32_t imm_r = GetImmRotate();
622   return DecodeImmBitMask(n, imm_s, imm_r, reg_size);
623 }
624 
625 // Logical immediates can't encode zero, so a return value of zero is used to
626 // indicate a failure case. Specifically, where the constraints on imm_s are
627 // not met.
GetSVEImmLogical() const628 uint64_t Instruction::GetSVEImmLogical() const {
629   int n = GetSVEBitN();
630   int imm_s = GetSVEImmSetBits();
631   int imm_r = GetSVEImmRotate();
632   int lane_size_in_bytes_log2 = GetSVEBitwiseImmLaneSizeInBytesLog2();
633   switch (lane_size_in_bytes_log2) {
634     case kDRegSizeInBytesLog2:
635     case kSRegSizeInBytesLog2:
636     case kHRegSizeInBytesLog2:
637     case kBRegSizeInBytesLog2: {
638       int lane_size_in_bits = 1 << (lane_size_in_bytes_log2 + 3);
639       return DecodeImmBitMask(n, imm_s, imm_r, lane_size_in_bits);
640     }
641     default:
642       return 0;
643   }
644 }
645 
GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const646 std::pair<int, int> Instruction::GetSVEImmShiftAndLaneSizeLog2(
647     bool is_predicated) const {
648   Instr tsize =
649       is_predicated ? ExtractBits<0x00C00300>() : ExtractBits<0x00D80000>();
650   Instr imm_3 =
651       is_predicated ? ExtractBits<0x000000E0>() : ExtractBits<0x00070000>();
652   if (tsize == 0) {
653     // The bit field `tsize` means undefined if it is zero, so return a
654     // convenience value kWMinInt to indicate a failure case.
655     return std::make_pair(kWMinInt, kWMinInt);
656   }
657 
658   int lane_size_in_bytes_log_2 = 32 - CountLeadingZeros(tsize, 32) - 1;
659   int esize = (1 << lane_size_in_bytes_log_2) * kBitsPerByte;
660   int shift = (2 * esize) - ((tsize << 3) | imm_3);
661   return std::make_pair(shift, lane_size_in_bytes_log_2);
662 }
663 
GetSVEMsizeFromDtype(bool is_signed,int dtype_h_lsb) const664 int Instruction::GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb) const {
665   Instr dtype_h = ExtractBits(dtype_h_lsb + 1, dtype_h_lsb);
666   if (is_signed) {
667     dtype_h = dtype_h ^ 0x3;
668   }
669   return dtype_h;
670 }
671 
GetSVEEsizeFromDtype(bool is_signed,int dtype_l_lsb) const672 int Instruction::GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb) const {
673   Instr dtype_l = ExtractBits(dtype_l_lsb + 1, dtype_l_lsb);
674   if (is_signed) {
675     dtype_l = dtype_l ^ 0x3;
676   }
677   return dtype_l;
678 }
679 
GetSVEBitwiseImmLaneSizeInBytesLog2() const680 int Instruction::GetSVEBitwiseImmLaneSizeInBytesLog2() const {
681   int n = GetSVEBitN();
682   int imm_s = GetSVEImmSetBits();
683   unsigned type_bitset =
684       (n << SVEImmSetBits_width) | (~imm_s & GetUintMask(SVEImmSetBits_width));
685 
686   // An lane size is constructed from the n and imm_s bits according to
687   // the following table:
688   //
689   // N   imms   size
690   // 0  0xxxxx   32
691   // 0  10xxxx   16
692   // 0  110xxx    8
693   // 0  1110xx    8
694   // 0  11110x    8
695   // 1  xxxxxx   64
696 
697   if (type_bitset == 0) {
698     // Bail out early since `HighestSetBitPosition` doesn't accept zero
699     // value input.
700     return -1;
701   }
702 
703   switch (HighestSetBitPosition(type_bitset)) {
704     case 6:
705       return kDRegSizeInBytesLog2;
706     case 5:
707       return kSRegSizeInBytesLog2;
708     case 4:
709       return kHRegSizeInBytesLog2;
710     case 3:
711     case 2:
712     case 1:
713       return kBRegSizeInBytesLog2;
714     default:
715       // RESERVED encoding.
716       return -1;
717   }
718 }
719 
DecodeImmBitMask(int32_t n,int32_t imm_s,int32_t imm_r,int32_t size) const720 uint64_t Instruction::DecodeImmBitMask(int32_t n,
721                                        int32_t imm_s,
722                                        int32_t imm_r,
723                                        int32_t size) const {
724   // An integer is constructed from the n, imm_s and imm_r bits according to
725   // the following table:
726   //
727   //  N   imms    immr    size        S             R
728   //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
729   //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
730   //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
731   //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
732   //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
733   //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
734   // (s bits must not be all set)
735   //
736   // A pattern is constructed of size bits, where the least significant S+1
737   // bits are set. The pattern is rotated right by R, and repeated across a
738   // 32 or 64-bit value, depending on destination register width.
739   //
740 
741   if (n == 1) {
742     if (imm_s == 0x3f) {
743       return 0;
744     }
745     uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
746     return RotateRight(bits, imm_r, 64);
747   } else {
748     if ((imm_s >> 1) == 0x1f) {
749       return 0;
750     }
751     for (int width = 0x20; width >= 0x2; width >>= 1) {
752       if ((imm_s & width) == 0) {
753         int mask = width - 1;
754         if ((imm_s & mask) == mask) {
755           return 0;
756         }
757         uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
758         return RepeatBitsAcrossReg(size,
759                                    RotateRight(bits, imm_r & mask, width),
760                                    width);
761       }
762     }
763   }
764   VIXL_UNREACHABLE();
765   return 0;
766 }
767 
768 
GetImmNEONabcdefgh() const769 uint32_t Instruction::GetImmNEONabcdefgh() const {
770   return GetImmNEONabc() << 5 | GetImmNEONdefgh();
771 }
772 
773 
Imm8ToFloat16(uint32_t imm8)774 Float16 Instruction::Imm8ToFloat16(uint32_t imm8) {
775   // Imm8: abcdefgh (8 bits)
776   // Half: aBbb.cdef.gh00.0000 (16 bits)
777   // where B is b ^ 1
778   uint32_t bits = imm8;
779   uint16_t bit7 = (bits >> 7) & 0x1;
780   uint16_t bit6 = (bits >> 6) & 0x1;
781   uint16_t bit5_to_0 = bits & 0x3f;
782   uint16_t result = (bit7 << 15) | ((4 - bit6) << 12) | (bit5_to_0 << 6);
783   return RawbitsToFloat16(result);
784 }
785 
786 
Imm8ToFP32(uint32_t imm8)787 float Instruction::Imm8ToFP32(uint32_t imm8) {
788   // Imm8: abcdefgh (8 bits)
789   // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
790   // where B is b ^ 1
791   uint32_t bits = imm8;
792   uint32_t bit7 = (bits >> 7) & 0x1;
793   uint32_t bit6 = (bits >> 6) & 0x1;
794   uint32_t bit5_to_0 = bits & 0x3f;
795   uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
796 
797   return RawbitsToFloat(result);
798 }
799 
800 
GetImmFP16() const801 Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
802 
803 
GetImmFP32() const804 float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
805 
806 
Imm8ToFP64(uint32_t imm8)807 double Instruction::Imm8ToFP64(uint32_t imm8) {
808   // Imm8: abcdefgh (8 bits)
809   // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
810   //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
811   // where B is b ^ 1
812   uint32_t bits = imm8;
813   uint64_t bit7 = (bits >> 7) & 0x1;
814   uint64_t bit6 = (bits >> 6) & 0x1;
815   uint64_t bit5_to_0 = bits & 0x3f;
816   uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
817 
818   return RawbitsToDouble(result);
819 }
820 
821 
GetImmFP64() const822 double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
823 
824 
GetImmNEONFP16() const825 Float16 Instruction::GetImmNEONFP16() const {
826   return Imm8ToFloat16(GetImmNEONabcdefgh());
827 }
828 
829 
GetImmNEONFP32() const830 float Instruction::GetImmNEONFP32() const {
831   return Imm8ToFP32(GetImmNEONabcdefgh());
832 }
833 
834 
GetImmNEONFP64() const835 double Instruction::GetImmNEONFP64() const {
836   return Imm8ToFP64(GetImmNEONabcdefgh());
837 }
838 
839 
CalcLSDataSize(LoadStoreOp op)840 unsigned CalcLSDataSize(LoadStoreOp op) {
841   VIXL_ASSERT((LSSize_offset + LSSize_width) == (kInstructionSize * 8));
842   unsigned size = static_cast<Instr>(op) >> LSSize_offset;
843   if ((op & LSVector_mask) != 0) {
844     // Vector register memory operations encode the access size in the "size"
845     // and "opc" fields.
846     if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
847       size = kQRegSizeInBytesLog2;
848     }
849   }
850   return size;
851 }
852 
853 
CalcLSPairDataSize(LoadStorePairOp op)854 unsigned CalcLSPairDataSize(LoadStorePairOp op) {
855   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
856   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
857   switch (op) {
858     case STP_q:
859     case LDP_q:
860       return kQRegSizeInBytesLog2;
861     case STP_x:
862     case LDP_x:
863     case STP_d:
864     case LDP_d:
865       return kXRegSizeInBytesLog2;
866     default:
867       return kWRegSizeInBytesLog2;
868   }
869 }
870 
871 
GetImmBranchRangeBitwidth(ImmBranchType branch_type)872 int Instruction::GetImmBranchRangeBitwidth(ImmBranchType branch_type) {
873   switch (branch_type) {
874     case UncondBranchType:
875       return ImmUncondBranch_width;
876     case CondBranchType:
877       return ImmCondBranch_width;
878     case CompareBranchType:
879       return ImmCmpBranch_width;
880     case TestBranchType:
881       return ImmTestBranch_width;
882     default:
883       VIXL_UNREACHABLE();
884       return 0;
885   }
886 }
887 
888 
GetImmBranchForwardRange(ImmBranchType branch_type)889 int32_t Instruction::GetImmBranchForwardRange(ImmBranchType branch_type) {
890   int32_t encoded_max = 1 << (GetImmBranchRangeBitwidth(branch_type) - 1);
891   return encoded_max * kInstructionSize;
892 }
893 
894 
IsValidImmPCOffset(ImmBranchType branch_type,int64_t offset)895 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
896                                      int64_t offset) {
897   return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
898 }
899 
900 
GetImmPCOffsetTarget() const901 const Instruction* Instruction::GetImmPCOffsetTarget() const {
902   const Instruction* base = this;
903   ptrdiff_t offset;
904   if (IsPCRelAddressing()) {
905     // ADR and ADRP.
906     offset = GetImmPCRel();
907     if (Mask(PCRelAddressingMask) == ADRP) {
908       base = AlignDown(base, kPageSize);
909       offset *= kPageSize;
910     } else {
911       VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
912     }
913   } else {
914     // All PC-relative branches.
915     VIXL_ASSERT(GetBranchType() != UnknownBranchType);
916     // Relative branch offsets are instruction-size-aligned.
917     offset = GetImmBranch() * static_cast<int>(kInstructionSize);
918   }
919   return base + offset;
920 }
921 
922 
GetImmBranch() const923 int Instruction::GetImmBranch() const {
924   switch (GetBranchType()) {
925     case CondBranchType:
926       return GetImmCondBranch();
927     case UncondBranchType:
928       return GetImmUncondBranch();
929     case CompareBranchType:
930       return GetImmCmpBranch();
931     case TestBranchType:
932       return GetImmTestBranch();
933     default:
934       VIXL_UNREACHABLE();
935   }
936   return 0;
937 }
938 
939 
SetImmPCOffsetTarget(const Instruction * target)940 void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
941   if (IsPCRelAddressing()) {
942     SetPCRelImmTarget(target);
943   } else {
944     SetBranchImmTarget(target);
945   }
946 }
947 
948 
SetPCRelImmTarget(const Instruction * target)949 void Instruction::SetPCRelImmTarget(const Instruction* target) {
950   ptrdiff_t imm21;
951   if ((Mask(PCRelAddressingMask) == ADR)) {
952     imm21 = target - this;
953   } else {
954     VIXL_ASSERT(Mask(PCRelAddressingMask) == ADRP);
955     uintptr_t this_page = reinterpret_cast<uintptr_t>(this) / kPageSize;
956     uintptr_t target_page = reinterpret_cast<uintptr_t>(target) / kPageSize;
957     imm21 = target_page - this_page;
958   }
959   Instr imm = Assembler::ImmPCRelAddress(static_cast<int32_t>(imm21));
960 
961   SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
962 }
963 
964 
SetBranchImmTarget(const Instruction * target)965 void Instruction::SetBranchImmTarget(const Instruction* target) {
966   VIXL_ASSERT(((target - this) & 3) == 0);
967   Instr branch_imm = 0;
968   uint32_t imm_mask = 0;
969   int offset = static_cast<int>((target - this) >> kInstructionSizeLog2);
970   switch (GetBranchType()) {
971     case CondBranchType: {
972       branch_imm = Assembler::ImmCondBranch(offset);
973       imm_mask = ImmCondBranch_mask;
974       break;
975     }
976     case UncondBranchType: {
977       branch_imm = Assembler::ImmUncondBranch(offset);
978       imm_mask = ImmUncondBranch_mask;
979       break;
980     }
981     case CompareBranchType: {
982       branch_imm = Assembler::ImmCmpBranch(offset);
983       imm_mask = ImmCmpBranch_mask;
984       break;
985     }
986     case TestBranchType: {
987       branch_imm = Assembler::ImmTestBranch(offset);
988       imm_mask = ImmTestBranch_mask;
989       break;
990     }
991     default:
992       VIXL_UNREACHABLE();
993   }
994   SetInstructionBits(Mask(~imm_mask) | branch_imm);
995 }
996 
997 
SetImmLLiteral(const Instruction * source)998 void Instruction::SetImmLLiteral(const Instruction* source) {
999   VIXL_ASSERT(IsWordAligned(source));
1000   ptrdiff_t offset = (source - this) >> kLiteralEntrySizeLog2;
1001   Instr imm = Assembler::ImmLLiteral(static_cast<int>(offset));
1002   Instr mask = ImmLLiteral_mask;
1003 
1004   SetInstructionBits(Mask(~mask) | imm);
1005 }
1006 
1007 
VectorFormatHalfWidth(VectorFormat vform)1008 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
1009   switch (vform) {
1010     case kFormat8H:
1011       return kFormat8B;
1012     case kFormat4S:
1013       return kFormat4H;
1014     case kFormat2D:
1015       return kFormat2S;
1016     case kFormatH:
1017       return kFormatB;
1018     case kFormatS:
1019       return kFormatH;
1020     case kFormatD:
1021       return kFormatS;
1022     case kFormatVnH:
1023       return kFormatVnB;
1024     case kFormatVnS:
1025       return kFormatVnH;
1026     case kFormatVnD:
1027       return kFormatVnS;
1028       break;
1029     default:
1030       VIXL_UNREACHABLE();
1031       return kFormatUndefined;
1032   }
1033 }
1034 
1035 
VectorFormatDoubleWidth(VectorFormat vform)1036 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
1037   VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S ||
1038               vform == kFormatB || vform == kFormatH || vform == kFormatS);
1039   switch (vform) {
1040     case kFormat8B:
1041       return kFormat8H;
1042     case kFormat4H:
1043       return kFormat4S;
1044     case kFormat2S:
1045       return kFormat2D;
1046     case kFormatB:
1047       return kFormatH;
1048     case kFormatH:
1049       return kFormatS;
1050     case kFormatS:
1051       return kFormatD;
1052     default:
1053       VIXL_UNREACHABLE();
1054       return kFormatUndefined;
1055   }
1056 }
1057 
1058 
VectorFormatFillQ(VectorFormat vform)1059 VectorFormat VectorFormatFillQ(VectorFormat vform) {
1060   switch (vform) {
1061     case kFormatB:
1062     case kFormat8B:
1063     case kFormat16B:
1064       return kFormat16B;
1065     case kFormatH:
1066     case kFormat4H:
1067     case kFormat8H:
1068       return kFormat8H;
1069     case kFormatS:
1070     case kFormat2S:
1071     case kFormat4S:
1072       return kFormat4S;
1073     case kFormatD:
1074     case kFormat1D:
1075     case kFormat2D:
1076       return kFormat2D;
1077     default:
1078       VIXL_UNREACHABLE();
1079       return kFormatUndefined;
1080   }
1081 }
1082 
VectorFormatHalfWidthDoubleLanes(VectorFormat vform)1083 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
1084   switch (vform) {
1085     case kFormat4H:
1086       return kFormat8B;
1087     case kFormat8H:
1088       return kFormat16B;
1089     case kFormat2S:
1090       return kFormat4H;
1091     case kFormat4S:
1092       return kFormat8H;
1093     case kFormat1D:
1094       return kFormat2S;
1095     case kFormat2D:
1096       return kFormat4S;
1097     case kFormatVnH:
1098       return kFormatVnB;
1099     case kFormatVnS:
1100       return kFormatVnH;
1101     case kFormatVnD:
1102       return kFormatVnS;
1103     default:
1104       VIXL_UNREACHABLE();
1105       return kFormatUndefined;
1106   }
1107 }
1108 
VectorFormatDoubleLanes(VectorFormat vform)1109 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
1110   VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
1111   switch (vform) {
1112     case kFormat8B:
1113       return kFormat16B;
1114     case kFormat4H:
1115       return kFormat8H;
1116     case kFormat2S:
1117       return kFormat4S;
1118     default:
1119       VIXL_UNREACHABLE();
1120       return kFormatUndefined;
1121   }
1122 }
1123 
1124 
VectorFormatHalfLanes(VectorFormat vform)1125 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
1126   VIXL_ASSERT(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
1127   switch (vform) {
1128     case kFormat16B:
1129       return kFormat8B;
1130     case kFormat8H:
1131       return kFormat4H;
1132     case kFormat4S:
1133       return kFormat2S;
1134     default:
1135       VIXL_UNREACHABLE();
1136       return kFormatUndefined;
1137   }
1138 }
1139 
1140 
ScalarFormatFromLaneSize(int lane_size_in_bits)1141 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits) {
1142   switch (lane_size_in_bits) {
1143     case 8:
1144       return kFormatB;
1145     case 16:
1146       return kFormatH;
1147     case 32:
1148       return kFormatS;
1149     case 64:
1150       return kFormatD;
1151     default:
1152       VIXL_UNREACHABLE();
1153       return kFormatUndefined;
1154   }
1155 }
1156 
1157 
IsSVEFormat(VectorFormat vform)1158 bool IsSVEFormat(VectorFormat vform) {
1159   switch (vform) {
1160     case kFormatVnB:
1161     case kFormatVnH:
1162     case kFormatVnS:
1163     case kFormatVnD:
1164     case kFormatVnQ:
1165       return true;
1166     default:
1167       return false;
1168   }
1169 }
1170 
1171 
SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes)1172 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes) {
1173   switch (lane_size_in_bytes) {
1174     case 1:
1175       return kFormatVnB;
1176     case 2:
1177       return kFormatVnH;
1178     case 4:
1179       return kFormatVnS;
1180     case 8:
1181       return kFormatVnD;
1182     case 16:
1183       return kFormatVnQ;
1184     default:
1185       VIXL_UNREACHABLE();
1186       return kFormatUndefined;
1187   }
1188 }
1189 
1190 
SVEFormatFromLaneSizeInBits(int lane_size_in_bits)1191 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits) {
1192   switch (lane_size_in_bits) {
1193     case 8:
1194     case 16:
1195     case 32:
1196     case 64:
1197     case 128:
1198       return SVEFormatFromLaneSizeInBytes(lane_size_in_bits / kBitsPerByte);
1199     default:
1200       VIXL_UNREACHABLE();
1201       return kFormatUndefined;
1202   }
1203 }
1204 
1205 
SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2)1206 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2) {
1207   switch (lane_size_in_bytes_log2) {
1208     case 0:
1209     case 1:
1210     case 2:
1211     case 3:
1212     case 4:
1213       return SVEFormatFromLaneSizeInBytes(1 << lane_size_in_bytes_log2);
1214     default:
1215       VIXL_UNREACHABLE();
1216       return kFormatUndefined;
1217   }
1218 }
1219 
1220 
ScalarFormatFromFormat(VectorFormat vform)1221 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
1222   return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1223 }
1224 
1225 
RegisterSizeInBitsFromFormat(VectorFormat vform)1226 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
1227   VIXL_ASSERT(vform != kFormatUndefined);
1228   VIXL_ASSERT(!IsSVEFormat(vform));
1229   switch (vform) {
1230     case kFormatB:
1231       return kBRegSize;
1232     case kFormatH:
1233       return kHRegSize;
1234     case kFormatS:
1235     case kFormat2H:
1236       return kSRegSize;
1237     case kFormatD:
1238     case kFormat8B:
1239     case kFormat4H:
1240     case kFormat2S:
1241     case kFormat1D:
1242       return kDRegSize;
1243     case kFormat16B:
1244     case kFormat8H:
1245     case kFormat4S:
1246     case kFormat2D:
1247       return kQRegSize;
1248     default:
1249       VIXL_UNREACHABLE();
1250       return 0;
1251   }
1252 }
1253 
1254 
RegisterSizeInBytesFromFormat(VectorFormat vform)1255 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
1256   return RegisterSizeInBitsFromFormat(vform) / 8;
1257 }
1258 
1259 
LaneSizeInBitsFromFormat(VectorFormat vform)1260 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
1261   VIXL_ASSERT(vform != kFormatUndefined);
1262   switch (vform) {
1263     case kFormatB:
1264     case kFormat8B:
1265     case kFormat16B:
1266     case kFormatVnB:
1267       return 8;
1268     case kFormatH:
1269     case kFormat2H:
1270     case kFormat4H:
1271     case kFormat8H:
1272     case kFormatVnH:
1273       return 16;
1274     case kFormatS:
1275     case kFormat2S:
1276     case kFormat4S:
1277     case kFormatVnS:
1278       return 32;
1279     case kFormatD:
1280     case kFormat1D:
1281     case kFormat2D:
1282     case kFormatVnD:
1283       return 64;
1284     case kFormatVnQ:
1285       return 128;
1286     default:
1287       VIXL_UNREACHABLE();
1288       return 0;
1289   }
1290 }
1291 
1292 
LaneSizeInBytesFromFormat(VectorFormat vform)1293 int LaneSizeInBytesFromFormat(VectorFormat vform) {
1294   return LaneSizeInBitsFromFormat(vform) / 8;
1295 }
1296 
1297 
LaneSizeInBytesLog2FromFormat(VectorFormat vform)1298 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
1299   VIXL_ASSERT(vform != kFormatUndefined);
1300   switch (vform) {
1301     case kFormatB:
1302     case kFormat8B:
1303     case kFormat16B:
1304     case kFormatVnB:
1305       return 0;
1306     case kFormatH:
1307     case kFormat2H:
1308     case kFormat4H:
1309     case kFormat8H:
1310     case kFormatVnH:
1311       return 1;
1312     case kFormatS:
1313     case kFormat2S:
1314     case kFormat4S:
1315     case kFormatVnS:
1316       return 2;
1317     case kFormatD:
1318     case kFormat1D:
1319     case kFormat2D:
1320     case kFormatVnD:
1321       return 3;
1322     case kFormatVnQ:
1323       return 4;
1324     default:
1325       VIXL_UNREACHABLE();
1326       return 0;
1327   }
1328 }
1329 
1330 
LaneCountFromFormat(VectorFormat vform)1331 int LaneCountFromFormat(VectorFormat vform) {
1332   VIXL_ASSERT(vform != kFormatUndefined);
1333   switch (vform) {
1334     case kFormat16B:
1335       return 16;
1336     case kFormat8B:
1337     case kFormat8H:
1338       return 8;
1339     case kFormat4H:
1340     case kFormat4S:
1341       return 4;
1342     case kFormat2H:
1343     case kFormat2S:
1344     case kFormat2D:
1345       return 2;
1346     case kFormat1D:
1347     case kFormatB:
1348     case kFormatH:
1349     case kFormatS:
1350     case kFormatD:
1351       return 1;
1352     default:
1353       VIXL_UNREACHABLE();
1354       return 0;
1355   }
1356 }
1357 
1358 
MaxLaneCountFromFormat(VectorFormat vform)1359 int MaxLaneCountFromFormat(VectorFormat vform) {
1360   VIXL_ASSERT(vform != kFormatUndefined);
1361   switch (vform) {
1362     case kFormatB:
1363     case kFormat8B:
1364     case kFormat16B:
1365       return 16;
1366     case kFormatH:
1367     case kFormat4H:
1368     case kFormat8H:
1369       return 8;
1370     case kFormatS:
1371     case kFormat2S:
1372     case kFormat4S:
1373       return 4;
1374     case kFormatD:
1375     case kFormat1D:
1376     case kFormat2D:
1377       return 2;
1378     default:
1379       VIXL_UNREACHABLE();
1380       return 0;
1381   }
1382 }
1383 
1384 
1385 // Does 'vform' indicate a vector format or a scalar format?
IsVectorFormat(VectorFormat vform)1386 bool IsVectorFormat(VectorFormat vform) {
1387   VIXL_ASSERT(vform != kFormatUndefined);
1388   switch (vform) {
1389     case kFormatB:
1390     case kFormatH:
1391     case kFormatS:
1392     case kFormatD:
1393       return false;
1394     default:
1395       return true;
1396   }
1397 }
1398 
1399 
MaxIntFromFormat(VectorFormat vform)1400 int64_t MaxIntFromFormat(VectorFormat vform) {
1401   int lane_size = LaneSizeInBitsFromFormat(vform);
1402   return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
1403 }
1404 
1405 
MinIntFromFormat(VectorFormat vform)1406 int64_t MinIntFromFormat(VectorFormat vform) {
1407   return -MaxIntFromFormat(vform) - 1;
1408 }
1409 
1410 
MaxUintFromFormat(VectorFormat vform)1411 uint64_t MaxUintFromFormat(VectorFormat vform) {
1412   return GetUintMask(LaneSizeInBitsFromFormat(vform));
1413 }
1414 
1415 }  // namespace aarch64
1416 }  // namespace vixl
1417