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
29#include "assembler-aarch64.h"
30
31namespace vixl {
32namespace aarch64 {
33
34static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
35                                    uint64_t value,
36                                    unsigned width) {
37  VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
38              (width == 32));
39  VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
40              (reg_size == kSRegSize) || (reg_size == kDRegSize));
41  uint64_t result = value & ((UINT64_C(1) << width) - 1);
42  for (unsigned i = width; i < reg_size; i *= 2) {
43    result |= (result << i);
44  }
45  return result;
46}
47
48bool Instruction::CanTakeSVEMovprfx(const char* form,
49                                    const Instruction* movprfx) const {
50  return CanTakeSVEMovprfx(Hash(form), movprfx);
51}
52
53bool Instruction::CanTakeSVEMovprfx(uint32_t form_hash,
54                                    const Instruction* movprfx) const {
55  bool movprfx_is_predicated = movprfx->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z;
56  bool movprfx_is_unpredicated =
57      movprfx->Mask(SVEConstructivePrefix_UnpredicatedMask) == MOVPRFX_z_z;
58  VIXL_ASSERT(movprfx_is_predicated != movprfx_is_unpredicated);
59
60  int movprfx_zd = movprfx->GetRd();
61  int movprfx_pg = movprfx_is_predicated ? movprfx->GetPgLow8() : -1;
62  VectorFormat movprfx_vform =
63      movprfx_is_predicated ? movprfx->GetSVEVectorFormat() : kFormatUndefined;
64
65  bool pg_matches_low8 = movprfx_pg == GetPgLow8();
66  bool vform_matches = movprfx_vform == GetSVEVectorFormat();
67  bool zd_matches = movprfx_zd == GetRd();
68  bool zd_isnt_zn = movprfx_zd != GetRn();
69  bool zd_isnt_zm = movprfx_zd != GetRm();
70
71  switch (form_hash) {
72    case "cdot_z_zzzi_s"_h:
73    case "sdot_z_zzzi_s"_h:
74    case "sudot_z_zzzi_s"_h:
75    case "udot_z_zzzi_s"_h:
76    case "usdot_z_zzzi_s"_h:
77      return (GetRd() != static_cast<int>(ExtractBits(18, 16))) &&
78             movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
79
80    case "cdot_z_zzzi_d"_h:
81    case "sdot_z_zzzi_d"_h:
82    case "udot_z_zzzi_d"_h:
83      return (GetRd() != static_cast<int>(ExtractBits(19, 16))) &&
84             movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
85
86    case "fmlalb_z_zzzi_s"_h:
87    case "fmlalt_z_zzzi_s"_h:
88    case "fmlslb_z_zzzi_s"_h:
89    case "fmlslt_z_zzzi_s"_h:
90    case "smlalb_z_zzzi_d"_h:
91    case "smlalb_z_zzzi_s"_h:
92    case "smlalt_z_zzzi_d"_h:
93    case "smlalt_z_zzzi_s"_h:
94    case "smlslb_z_zzzi_d"_h:
95    case "smlslb_z_zzzi_s"_h:
96    case "smlslt_z_zzzi_d"_h:
97    case "smlslt_z_zzzi_s"_h:
98    case "sqdmlalb_z_zzzi_d"_h:
99    case "sqdmlalb_z_zzzi_s"_h:
100    case "sqdmlalt_z_zzzi_d"_h:
101    case "sqdmlalt_z_zzzi_s"_h:
102    case "sqdmlslb_z_zzzi_d"_h:
103    case "sqdmlslb_z_zzzi_s"_h:
104    case "sqdmlslt_z_zzzi_d"_h:
105    case "sqdmlslt_z_zzzi_s"_h:
106    case "umlalb_z_zzzi_d"_h:
107    case "umlalb_z_zzzi_s"_h:
108    case "umlalt_z_zzzi_d"_h:
109    case "umlalt_z_zzzi_s"_h:
110    case "umlslb_z_zzzi_d"_h:
111    case "umlslb_z_zzzi_s"_h:
112    case "umlslt_z_zzzi_d"_h:
113    case "umlslt_z_zzzi_s"_h:
114      return (GetRd() != GetSVEMulLongZmAndIndex().first) &&
115             movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
116
117    case "cmla_z_zzzi_h"_h:
118    case "cmla_z_zzzi_s"_h:
119    case "fcmla_z_zzzi_h"_h:
120    case "fcmla_z_zzzi_s"_h:
121    case "fmla_z_zzzi_d"_h:
122    case "fmla_z_zzzi_h"_h:
123    case "fmla_z_zzzi_s"_h:
124    case "fmls_z_zzzi_d"_h:
125    case "fmls_z_zzzi_h"_h:
126    case "fmls_z_zzzi_s"_h:
127    case "mla_z_zzzi_d"_h:
128    case "mla_z_zzzi_h"_h:
129    case "mla_z_zzzi_s"_h:
130    case "mls_z_zzzi_d"_h:
131    case "mls_z_zzzi_h"_h:
132    case "mls_z_zzzi_s"_h:
133    case "sqrdcmlah_z_zzzi_h"_h:
134    case "sqrdcmlah_z_zzzi_s"_h:
135    case "sqrdmlah_z_zzzi_d"_h:
136    case "sqrdmlah_z_zzzi_h"_h:
137    case "sqrdmlah_z_zzzi_s"_h:
138    case "sqrdmlsh_z_zzzi_d"_h:
139    case "sqrdmlsh_z_zzzi_h"_h:
140    case "sqrdmlsh_z_zzzi_s"_h:
141      return (GetRd() != GetSVEMulZmAndIndex().first) &&
142             movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
143
144    case "adclb_z_zzz"_h:
145    case "adclt_z_zzz"_h:
146    case "bcax_z_zzz"_h:
147    case "bsl1n_z_zzz"_h:
148    case "bsl2n_z_zzz"_h:
149    case "bsl_z_zzz"_h:
150    case "cdot_z_zzz"_h:
151    case "cmla_z_zzz"_h:
152    case "eor3_z_zzz"_h:
153    case "eorbt_z_zz"_h:
154    case "eortb_z_zz"_h:
155    case "fmlalb_z_zzz"_h:
156    case "fmlalt_z_zzz"_h:
157    case "fmlslb_z_zzz"_h:
158    case "fmlslt_z_zzz"_h:
159    case "nbsl_z_zzz"_h:
160    case "saba_z_zzz"_h:
161    case "sabalb_z_zzz"_h:
162    case "sabalt_z_zzz"_h:
163    case "sbclb_z_zzz"_h:
164    case "sbclt_z_zzz"_h:
165    case "sdot_z_zzz"_h:
166    case "smlalb_z_zzz"_h:
167    case "smlalt_z_zzz"_h:
168    case "smlslb_z_zzz"_h:
169    case "smlslt_z_zzz"_h:
170    case "sqdmlalb_z_zzz"_h:
171    case "sqdmlalbt_z_zzz"_h:
172    case "sqdmlalt_z_zzz"_h:
173    case "sqdmlslb_z_zzz"_h:
174    case "sqdmlslbt_z_zzz"_h:
175    case "sqdmlslt_z_zzz"_h:
176    case "sqrdcmlah_z_zzz"_h:
177    case "sqrdmlah_z_zzz"_h:
178    case "sqrdmlsh_z_zzz"_h:
179    case "uaba_z_zzz"_h:
180    case "uabalb_z_zzz"_h:
181    case "uabalt_z_zzz"_h:
182    case "udot_z_zzz"_h:
183    case "umlalb_z_zzz"_h:
184    case "umlalt_z_zzz"_h:
185    case "umlslb_z_zzz"_h:
186    case "umlslt_z_zzz"_h:
187    case "usdot_z_zzz_s"_h:
188    case "fmmla_z_zzz_s"_h:
189    case "fmmla_z_zzz_d"_h:
190    case "smmla_z_zzz"_h:
191    case "ummla_z_zzz"_h:
192    case "usmmla_z_zzz"_h:
193      return movprfx_is_unpredicated && zd_isnt_zm && zd_isnt_zn && zd_matches;
194
195    case "addp_z_p_zz"_h:
196    case "cadd_z_zz"_h:
197    case "clasta_z_p_zz"_h:
198    case "clastb_z_p_zz"_h:
199    case "decd_z_zs"_h:
200    case "dech_z_zs"_h:
201    case "decw_z_zs"_h:
202    case "ext_z_zi_des"_h:
203    case "faddp_z_p_zz"_h:
204    case "fmaxnmp_z_p_zz"_h:
205    case "fmaxp_z_p_zz"_h:
206    case "fminnmp_z_p_zz"_h:
207    case "fminp_z_p_zz"_h:
208    case "ftmad_z_zzi"_h:
209    case "incd_z_zs"_h:
210    case "inch_z_zs"_h:
211    case "incw_z_zs"_h:
212    case "insr_z_v"_h:
213    case "smaxp_z_p_zz"_h:
214    case "sminp_z_p_zz"_h:
215    case "splice_z_p_zz_des"_h:
216    case "sqcadd_z_zz"_h:
217    case "sqdecd_z_zs"_h:
218    case "sqdech_z_zs"_h:
219    case "sqdecw_z_zs"_h:
220    case "sqincd_z_zs"_h:
221    case "sqinch_z_zs"_h:
222    case "sqincw_z_zs"_h:
223    case "srsra_z_zi"_h:
224    case "ssra_z_zi"_h:
225    case "umaxp_z_p_zz"_h:
226    case "uminp_z_p_zz"_h:
227    case "uqdecd_z_zs"_h:
228    case "uqdech_z_zs"_h:
229    case "uqdecw_z_zs"_h:
230    case "uqincd_z_zs"_h:
231    case "uqinch_z_zs"_h:
232    case "uqincw_z_zs"_h:
233    case "ursra_z_zi"_h:
234    case "usra_z_zi"_h:
235    case "xar_z_zzi"_h:
236      return movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
237
238    case "add_z_zi"_h:
239    case "and_z_zi"_h:
240    case "decp_z_p_z"_h:
241    case "eor_z_zi"_h:
242    case "incp_z_p_z"_h:
243    case "insr_z_r"_h:
244    case "mul_z_zi"_h:
245    case "orr_z_zi"_h:
246    case "smax_z_zi"_h:
247    case "smin_z_zi"_h:
248    case "sqadd_z_zi"_h:
249    case "sqdecp_z_p_z"_h:
250    case "sqincp_z_p_z"_h:
251    case "sqsub_z_zi"_h:
252    case "sub_z_zi"_h:
253    case "subr_z_zi"_h:
254    case "umax_z_zi"_h:
255    case "umin_z_zi"_h:
256    case "uqadd_z_zi"_h:
257    case "uqdecp_z_p_z"_h:
258    case "uqincp_z_p_z"_h:
259    case "uqsub_z_zi"_h:
260      return movprfx_is_unpredicated && zd_matches;
261
262    case "cpy_z_p_i"_h:
263      if (movprfx_is_predicated) {
264        if (!vform_matches) return false;
265        if (movprfx_pg != GetRx<19, 16>()) return false;
266      }
267      // Only the merging form can take movprfx.
268      if (ExtractBit(14) == 0) return false;
269      return zd_matches;
270
271    case "fcpy_z_p_i"_h:
272      return (movprfx_is_unpredicated ||
273              ((movprfx_pg == GetRx<19, 16>()) && vform_matches)) &&
274             zd_matches;
275
276    case "flogb_z_p_z"_h:
277      return (movprfx_is_unpredicated ||
278              ((movprfx_vform == GetSVEVectorFormat(17)) && pg_matches_low8)) &&
279             zd_isnt_zn && zd_matches;
280
281    case "asr_z_p_zi"_h:
282    case "asrd_z_p_zi"_h:
283    case "lsl_z_p_zi"_h:
284    case "lsr_z_p_zi"_h:
285    case "sqshl_z_p_zi"_h:
286    case "sqshlu_z_p_zi"_h:
287    case "srshr_z_p_zi"_h:
288    case "uqshl_z_p_zi"_h:
289    case "urshr_z_p_zi"_h:
290      return (movprfx_is_unpredicated ||
291              ((movprfx_vform ==
292                SVEFormatFromLaneSizeInBytesLog2(
293                    GetSVEImmShiftAndLaneSizeLog2(true).second)) &&
294               pg_matches_low8)) &&
295             zd_matches;
296
297    case "fcvt_z_p_z_d2h"_h:
298    case "fcvt_z_p_z_d2s"_h:
299    case "fcvt_z_p_z_h2d"_h:
300    case "fcvt_z_p_z_s2d"_h:
301    case "fcvtx_z_p_z_d2s"_h:
302    case "fcvtzs_z_p_z_d2w"_h:
303    case "fcvtzs_z_p_z_d2x"_h:
304    case "fcvtzs_z_p_z_fp162x"_h:
305    case "fcvtzs_z_p_z_s2x"_h:
306    case "fcvtzu_z_p_z_d2w"_h:
307    case "fcvtzu_z_p_z_d2x"_h:
308    case "fcvtzu_z_p_z_fp162x"_h:
309    case "fcvtzu_z_p_z_s2x"_h:
310    case "scvtf_z_p_z_w2d"_h:
311    case "scvtf_z_p_z_x2d"_h:
312    case "scvtf_z_p_z_x2fp16"_h:
313    case "scvtf_z_p_z_x2s"_h:
314    case "ucvtf_z_p_z_w2d"_h:
315    case "ucvtf_z_p_z_x2d"_h:
316    case "ucvtf_z_p_z_x2fp16"_h:
317    case "ucvtf_z_p_z_x2s"_h:
318      return (movprfx_is_unpredicated ||
319              ((movprfx_vform == kFormatVnD) && pg_matches_low8)) &&
320             zd_isnt_zn && zd_matches;
321
322    case "fcvtzs_z_p_z_fp162h"_h:
323    case "fcvtzu_z_p_z_fp162h"_h:
324    case "scvtf_z_p_z_h2fp16"_h:
325    case "ucvtf_z_p_z_h2fp16"_h:
326      return (movprfx_is_unpredicated ||
327              ((movprfx_vform == kFormatVnH) && pg_matches_low8)) &&
328             zd_isnt_zn && zd_matches;
329
330    case "fcvt_z_p_z_h2s"_h:
331    case "fcvt_z_p_z_s2h"_h:
332    case "fcvtzs_z_p_z_fp162w"_h:
333    case "fcvtzs_z_p_z_s2w"_h:
334    case "fcvtzu_z_p_z_fp162w"_h:
335    case "fcvtzu_z_p_z_s2w"_h:
336    case "scvtf_z_p_z_w2fp16"_h:
337    case "scvtf_z_p_z_w2s"_h:
338    case "ucvtf_z_p_z_w2fp16"_h:
339    case "ucvtf_z_p_z_w2s"_h:
340      return (movprfx_is_unpredicated ||
341              ((movprfx_vform == kFormatVnS) && pg_matches_low8)) &&
342             zd_isnt_zn && zd_matches;
343
344    case "fcmla_z_p_zzz"_h:
345    case "fmad_z_p_zzz"_h:
346    case "fmla_z_p_zzz"_h:
347    case "fmls_z_p_zzz"_h:
348    case "fmsb_z_p_zzz"_h:
349    case "fnmad_z_p_zzz"_h:
350    case "fnmla_z_p_zzz"_h:
351    case "fnmls_z_p_zzz"_h:
352    case "fnmsb_z_p_zzz"_h:
353    case "mad_z_p_zzz"_h:
354    case "mla_z_p_zzz"_h:
355    case "mls_z_p_zzz"_h:
356    case "msb_z_p_zzz"_h:
357      return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
358             zd_isnt_zm && zd_isnt_zn && zd_matches;
359
360    case "abs_z_p_z"_h:
361    case "add_z_p_zz"_h:
362    case "and_z_p_zz"_h:
363    case "asr_z_p_zw"_h:
364    case "asr_z_p_zz"_h:
365    case "asrr_z_p_zz"_h:
366    case "bic_z_p_zz"_h:
367    case "cls_z_p_z"_h:
368    case "clz_z_p_z"_h:
369    case "cnot_z_p_z"_h:
370    case "cnt_z_p_z"_h:
371    case "cpy_z_p_v"_h:
372    case "eor_z_p_zz"_h:
373    case "fabd_z_p_zz"_h:
374    case "fabs_z_p_z"_h:
375    case "fadd_z_p_zz"_h:
376    case "fcadd_z_p_zz"_h:
377    case "fdiv_z_p_zz"_h:
378    case "fdivr_z_p_zz"_h:
379    case "fmax_z_p_zz"_h:
380    case "fmaxnm_z_p_zz"_h:
381    case "fmin_z_p_zz"_h:
382    case "fminnm_z_p_zz"_h:
383    case "fmul_z_p_zz"_h:
384    case "fmulx_z_p_zz"_h:
385    case "fneg_z_p_z"_h:
386    case "frecpx_z_p_z"_h:
387    case "frinta_z_p_z"_h:
388    case "frinti_z_p_z"_h:
389    case "frintm_z_p_z"_h:
390    case "frintn_z_p_z"_h:
391    case "frintp_z_p_z"_h:
392    case "frintx_z_p_z"_h:
393    case "frintz_z_p_z"_h:
394    case "fscale_z_p_zz"_h:
395    case "fsqrt_z_p_z"_h:
396    case "fsub_z_p_zz"_h:
397    case "fsubr_z_p_zz"_h:
398    case "lsl_z_p_zw"_h:
399    case "lsl_z_p_zz"_h:
400    case "lslr_z_p_zz"_h:
401    case "lsr_z_p_zw"_h:
402    case "lsr_z_p_zz"_h:
403    case "lsrr_z_p_zz"_h:
404    case "mul_z_p_zz"_h:
405    case "neg_z_p_z"_h:
406    case "not_z_p_z"_h:
407    case "orr_z_p_zz"_h:
408    case "rbit_z_p_z"_h:
409    case "revb_z_z"_h:
410    case "revh_z_z"_h:
411    case "revw_z_z"_h:
412    case "sabd_z_p_zz"_h:
413    case "sadalp_z_p_z"_h:
414    case "sdiv_z_p_zz"_h:
415    case "sdivr_z_p_zz"_h:
416    case "shadd_z_p_zz"_h:
417    case "shsub_z_p_zz"_h:
418    case "shsubr_z_p_zz"_h:
419    case "smax_z_p_zz"_h:
420    case "smin_z_p_zz"_h:
421    case "smulh_z_p_zz"_h:
422    case "sqabs_z_p_z"_h:
423    case "sqadd_z_p_zz"_h:
424    case "sqneg_z_p_z"_h:
425    case "sqrshl_z_p_zz"_h:
426    case "sqrshlr_z_p_zz"_h:
427    case "sqshl_z_p_zz"_h:
428    case "sqshlr_z_p_zz"_h:
429    case "sqsub_z_p_zz"_h:
430    case "sqsubr_z_p_zz"_h:
431    case "srhadd_z_p_zz"_h:
432    case "srshl_z_p_zz"_h:
433    case "srshlr_z_p_zz"_h:
434    case "sub_z_p_zz"_h:
435    case "subr_z_p_zz"_h:
436    case "suqadd_z_p_zz"_h:
437    case "sxtb_z_p_z"_h:
438    case "sxth_z_p_z"_h:
439    case "sxtw_z_p_z"_h:
440    case "uabd_z_p_zz"_h:
441    case "uadalp_z_p_z"_h:
442    case "udiv_z_p_zz"_h:
443    case "udivr_z_p_zz"_h:
444    case "uhadd_z_p_zz"_h:
445    case "uhsub_z_p_zz"_h:
446    case "uhsubr_z_p_zz"_h:
447    case "umax_z_p_zz"_h:
448    case "umin_z_p_zz"_h:
449    case "umulh_z_p_zz"_h:
450    case "uqadd_z_p_zz"_h:
451    case "uqrshl_z_p_zz"_h:
452    case "uqrshlr_z_p_zz"_h:
453    case "uqshl_z_p_zz"_h:
454    case "uqshlr_z_p_zz"_h:
455    case "uqsub_z_p_zz"_h:
456    case "uqsubr_z_p_zz"_h:
457    case "urecpe_z_p_z"_h:
458    case "urhadd_z_p_zz"_h:
459    case "urshl_z_p_zz"_h:
460    case "urshlr_z_p_zz"_h:
461    case "ursqrte_z_p_z"_h:
462    case "usqadd_z_p_zz"_h:
463    case "uxtb_z_p_z"_h:
464    case "uxth_z_p_z"_h:
465    case "uxtw_z_p_z"_h:
466      return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
467             zd_isnt_zn && zd_matches;
468
469    case "cpy_z_p_r"_h:
470    case "fadd_z_p_zs"_h:
471    case "fmax_z_p_zs"_h:
472    case "fmaxnm_z_p_zs"_h:
473    case "fmin_z_p_zs"_h:
474    case "fminnm_z_p_zs"_h:
475    case "fmul_z_p_zs"_h:
476    case "fsub_z_p_zs"_h:
477    case "fsubr_z_p_zs"_h:
478      return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
479             zd_matches;
480    default:
481      return false;
482  }
483}  // NOLINT(readability/fn_size)
484
485bool Instruction::IsLoad() const {
486  if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
487    return false;
488  }
489
490  if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
491    return Mask(LoadStorePairLBit) != 0;
492  } else {
493    LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
494    switch (op) {
495      case LDRB_w:
496      case LDRH_w:
497      case LDR_w:
498      case LDR_x:
499      case LDRSB_w:
500      case LDRSB_x:
501      case LDRSH_w:
502      case LDRSH_x:
503      case LDRSW_x:
504      case LDR_b:
505      case LDR_h:
506      case LDR_s:
507      case LDR_d:
508      case LDR_q:
509        return true;
510      default:
511        return false;
512    }
513  }
514}
515
516
517bool Instruction::IsStore() const {
518  if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
519    return false;
520  }
521
522  if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
523    return Mask(LoadStorePairLBit) == 0;
524  } else {
525    LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
526    switch (op) {
527      case STRB_w:
528      case STRH_w:
529      case STR_w:
530      case STR_x:
531      case STR_b:
532      case STR_h:
533      case STR_s:
534      case STR_d:
535      case STR_q:
536        return true;
537      default:
538        return false;
539    }
540  }
541}
542
543
544std::pair<int, int> Instruction::GetSVEPermuteIndexAndLaneSizeLog2() const {
545  uint32_t imm_2 = ExtractBits<0x00C00000>();
546  uint32_t tsz_5 = ExtractBits<0x001F0000>();
547  uint32_t imm_7 = (imm_2 << 5) | tsz_5;
548  int lane_size_in_byte_log_2 = std::min(CountTrailingZeros(tsz_5), 5);
549  int index = ExtractUnsignedBitfield32(6, lane_size_in_byte_log_2 + 1, imm_7);
550  return std::make_pair(index, lane_size_in_byte_log_2);
551}
552
553// Get the register and index for SVE indexed multiplies encoded in the forms:
554//  .h : Zm = <18:16>, index = <22><20:19>
555//  .s : Zm = <18:16>, index = <20:19>
556//  .d : Zm = <19:16>, index = <20>
557std::pair<int, int> Instruction::GetSVEMulZmAndIndex() const {
558  int reg_code = GetRmLow16();
559  int index = ExtractBits(20, 19);
560
561  // For .h, index uses bit zero of the size field, so kFormatVnB below implies
562  // half-word lane, with most-significant bit of the index zero.
563  switch (GetSVEVectorFormat()) {
564    case kFormatVnD:
565      index >>= 1;  // Only bit 20 in the index for D lanes.
566      break;
567    case kFormatVnH:
568      index += 4;  // Bit 22 is the top bit of index.
569      VIXL_FALLTHROUGH();
570    case kFormatVnB:
571    case kFormatVnS:
572      reg_code &= 7;  // Three bits used for the register.
573      break;
574    default:
575      VIXL_UNIMPLEMENTED();
576      break;
577  }
578  return std::make_pair(reg_code, index);
579}
580
581// Get the register and index for SVE indexed long multiplies encoded in the
582// forms:
583//  .h : Zm = <18:16>, index = <20:19><11>
584//  .s : Zm = <19:16>, index = <20><11>
585std::pair<int, int> Instruction::GetSVEMulLongZmAndIndex() const {
586  int reg_code = GetRmLow16();
587  int index = ExtractBit(11);
588
589  // For long multiplies, the SVE size field <23:22> encodes the destination
590  // element size. The source element size is half the width.
591  switch (GetSVEVectorFormat()) {
592    case kFormatVnS:
593      reg_code &= 7;
594      index |= ExtractBits(20, 19) << 1;
595      break;
596    case kFormatVnD:
597      index |= ExtractBit(20) << 1;
598      break;
599    default:
600      VIXL_UNIMPLEMENTED();
601      break;
602  }
603  return std::make_pair(reg_code, index);
604}
605
606// Logical immediates can't encode zero, so a return value of zero is used to
607// indicate a failure case. Specifically, where the constraints on imm_s are
608// not met.
609uint64_t Instruction::GetImmLogical() const {
610  unsigned reg_size = GetSixtyFourBits() ? kXRegSize : kWRegSize;
611  int32_t n = GetBitN();
612  int32_t imm_s = GetImmSetBits();
613  int32_t imm_r = GetImmRotate();
614  return DecodeImmBitMask(n, imm_s, imm_r, reg_size);
615}
616
617// Logical immediates can't encode zero, so a return value of zero is used to
618// indicate a failure case. Specifically, where the constraints on imm_s are
619// not met.
620uint64_t Instruction::GetSVEImmLogical() const {
621  int n = GetSVEBitN();
622  int imm_s = GetSVEImmSetBits();
623  int imm_r = GetSVEImmRotate();
624  int lane_size_in_bytes_log2 = GetSVEBitwiseImmLaneSizeInBytesLog2();
625  switch (lane_size_in_bytes_log2) {
626    case kDRegSizeInBytesLog2:
627    case kSRegSizeInBytesLog2:
628    case kHRegSizeInBytesLog2:
629    case kBRegSizeInBytesLog2: {
630      int lane_size_in_bits = 1 << (lane_size_in_bytes_log2 + 3);
631      return DecodeImmBitMask(n, imm_s, imm_r, lane_size_in_bits);
632    }
633    default:
634      return 0;
635  }
636}
637
638std::pair<int, int> Instruction::GetSVEImmShiftAndLaneSizeLog2(
639    bool is_predicated) const {
640  Instr tsize =
641      is_predicated ? ExtractBits<0x00C00300>() : ExtractBits<0x00D80000>();
642  Instr imm_3 =
643      is_predicated ? ExtractBits<0x000000E0>() : ExtractBits<0x00070000>();
644  if (tsize == 0) {
645    // The bit field `tsize` means undefined if it is zero, so return a
646    // convenience value kWMinInt to indicate a failure case.
647    return std::make_pair(kWMinInt, kWMinInt);
648  }
649
650  int lane_size_in_bytes_log_2 = 32 - CountLeadingZeros(tsize, 32) - 1;
651  int esize = (1 << lane_size_in_bytes_log_2) * kBitsPerByte;
652  int shift = (2 * esize) - ((tsize << 3) | imm_3);
653  return std::make_pair(shift, lane_size_in_bytes_log_2);
654}
655
656int Instruction::GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb) const {
657  Instr dtype_h = ExtractBits(dtype_h_lsb + 1, dtype_h_lsb);
658  if (is_signed) {
659    dtype_h = dtype_h ^ 0x3;
660  }
661  return dtype_h;
662}
663
664int Instruction::GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb) const {
665  Instr dtype_l = ExtractBits(dtype_l_lsb + 1, dtype_l_lsb);
666  if (is_signed) {
667    dtype_l = dtype_l ^ 0x3;
668  }
669  return dtype_l;
670}
671
672int Instruction::GetSVEBitwiseImmLaneSizeInBytesLog2() const {
673  int n = GetSVEBitN();
674  int imm_s = GetSVEImmSetBits();
675  unsigned type_bitset =
676      (n << SVEImmSetBits_width) | (~imm_s & GetUintMask(SVEImmSetBits_width));
677
678  // An lane size is constructed from the n and imm_s bits according to
679  // the following table:
680  //
681  // N   imms   size
682  // 0  0xxxxx   32
683  // 0  10xxxx   16
684  // 0  110xxx    8
685  // 0  1110xx    8
686  // 0  11110x    8
687  // 1  xxxxxx   64
688
689  if (type_bitset == 0) {
690    // Bail out early since `HighestSetBitPosition` doesn't accept zero
691    // value input.
692    return -1;
693  }
694
695  switch (HighestSetBitPosition(type_bitset)) {
696    case 6:
697      return kDRegSizeInBytesLog2;
698    case 5:
699      return kSRegSizeInBytesLog2;
700    case 4:
701      return kHRegSizeInBytesLog2;
702    case 3:
703    case 2:
704    case 1:
705      return kBRegSizeInBytesLog2;
706    default:
707      // RESERVED encoding.
708      return -1;
709  }
710}
711
712int Instruction::GetSVEExtractImmediate() const {
713  const int imm8h_mask = 0x001F0000;
714  const int imm8l_mask = 0x00001C00;
715  return ExtractBits<imm8h_mask | imm8l_mask>();
716}
717
718uint64_t Instruction::DecodeImmBitMask(int32_t n,
719                                       int32_t imm_s,
720                                       int32_t imm_r,
721                                       int32_t size) const {
722  // An integer is constructed from the n, imm_s and imm_r bits according to
723  // the following table:
724  //
725  //  N   imms    immr    size        S             R
726  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
727  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
728  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
729  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
730  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
731  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
732  // (s bits must not be all set)
733  //
734  // A pattern is constructed of size bits, where the least significant S+1
735  // bits are set. The pattern is rotated right by R, and repeated across a
736  // 32 or 64-bit value, depending on destination register width.
737  //
738
739  if (n == 1) {
740    if (imm_s == 0x3f) {
741      return 0;
742    }
743    uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
744    return RotateRight(bits, imm_r, 64);
745  } else {
746    if ((imm_s >> 1) == 0x1f) {
747      return 0;
748    }
749    for (int width = 0x20; width >= 0x2; width >>= 1) {
750      if ((imm_s & width) == 0) {
751        int mask = width - 1;
752        if ((imm_s & mask) == mask) {
753          return 0;
754        }
755        uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
756        return RepeatBitsAcrossReg(size,
757                                   RotateRight(bits, imm_r & mask, width),
758                                   width);
759      }
760    }
761  }
762  VIXL_UNREACHABLE();
763  return 0;
764}
765
766
767uint32_t Instruction::GetImmNEONabcdefgh() const {
768  return GetImmNEONabc() << 5 | GetImmNEONdefgh();
769}
770
771
772Float16 Instruction::Imm8ToFloat16(uint32_t imm8) {
773  // Imm8: abcdefgh (8 bits)
774  // Half: aBbb.cdef.gh00.0000 (16 bits)
775  // where B is b ^ 1
776  uint32_t bits = imm8;
777  uint16_t bit7 = (bits >> 7) & 0x1;
778  uint16_t bit6 = (bits >> 6) & 0x1;
779  uint16_t bit5_to_0 = bits & 0x3f;
780  uint16_t result = (bit7 << 15) | ((4 - bit6) << 12) | (bit5_to_0 << 6);
781  return RawbitsToFloat16(result);
782}
783
784
785float Instruction::Imm8ToFP32(uint32_t imm8) {
786  // Imm8: abcdefgh (8 bits)
787  // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
788  // where B is b ^ 1
789  uint32_t bits = imm8;
790  uint32_t bit7 = (bits >> 7) & 0x1;
791  uint32_t bit6 = (bits >> 6) & 0x1;
792  uint32_t bit5_to_0 = bits & 0x3f;
793  uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
794
795  return RawbitsToFloat(result);
796}
797
798
799Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
800
801
802float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
803
804
805double Instruction::Imm8ToFP64(uint32_t imm8) {
806  // Imm8: abcdefgh (8 bits)
807  // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
808  //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
809  // where B is b ^ 1
810  uint32_t bits = imm8;
811  uint64_t bit7 = (bits >> 7) & 0x1;
812  uint64_t bit6 = (bits >> 6) & 0x1;
813  uint64_t bit5_to_0 = bits & 0x3f;
814  uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
815
816  return RawbitsToDouble(result);
817}
818
819
820double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
821
822
823Float16 Instruction::GetImmNEONFP16() const {
824  return Imm8ToFloat16(GetImmNEONabcdefgh());
825}
826
827
828float Instruction::GetImmNEONFP32() const {
829  return Imm8ToFP32(GetImmNEONabcdefgh());
830}
831
832
833double Instruction::GetImmNEONFP64() const {
834  return Imm8ToFP64(GetImmNEONabcdefgh());
835}
836
837
838unsigned CalcLSDataSize(LoadStoreOp op) {
839  VIXL_ASSERT((LSSize_offset + LSSize_width) == (kInstructionSize * 8));
840  unsigned size = static_cast<Instr>(op) >> LSSize_offset;
841  if ((op & LSVector_mask) != 0) {
842    // Vector register memory operations encode the access size in the "size"
843    // and "opc" fields.
844    if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
845      size = kQRegSizeInBytesLog2;
846    }
847  }
848  return size;
849}
850
851
852unsigned CalcLSPairDataSize(LoadStorePairOp op) {
853  VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
854  VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
855  switch (op) {
856    case STP_q:
857    case LDP_q:
858      return kQRegSizeInBytesLog2;
859    case STP_x:
860    case LDP_x:
861    case STP_d:
862    case LDP_d:
863      return kXRegSizeInBytesLog2;
864    default:
865      return kWRegSizeInBytesLog2;
866  }
867}
868
869
870int Instruction::GetImmBranchRangeBitwidth(ImmBranchType branch_type) {
871  switch (branch_type) {
872    case UncondBranchType:
873      return ImmUncondBranch_width;
874    case CondBranchType:
875      return ImmCondBranch_width;
876    case CompareBranchType:
877      return ImmCmpBranch_width;
878    case TestBranchType:
879      return ImmTestBranch_width;
880    default:
881      VIXL_UNREACHABLE();
882      return 0;
883  }
884}
885
886
887int32_t Instruction::GetImmBranchForwardRange(ImmBranchType branch_type) {
888  int32_t encoded_max = 1 << (GetImmBranchRangeBitwidth(branch_type) - 1);
889  return encoded_max * kInstructionSize;
890}
891
892
893bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
894                                     int64_t offset) {
895  return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
896}
897
898
899const Instruction* Instruction::GetImmPCOffsetTarget() const {
900  const Instruction* base = this;
901  ptrdiff_t offset;
902  if (IsPCRelAddressing()) {
903    // ADR and ADRP.
904    offset = GetImmPCRel();
905    if (Mask(PCRelAddressingMask) == ADRP) {
906      base = AlignDown(base, kPageSize);
907      offset *= kPageSize;
908    } else {
909      VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
910    }
911  } else {
912    // All PC-relative branches.
913    VIXL_ASSERT(GetBranchType() != UnknownBranchType);
914    // Relative branch offsets are instruction-size-aligned.
915    offset = GetImmBranch() * static_cast<int>(kInstructionSize);
916  }
917  return base + offset;
918}
919
920
921int Instruction::GetImmBranch() const {
922  switch (GetBranchType()) {
923    case CondBranchType:
924      return GetImmCondBranch();
925    case UncondBranchType:
926      return GetImmUncondBranch();
927    case CompareBranchType:
928      return GetImmCmpBranch();
929    case TestBranchType:
930      return GetImmTestBranch();
931    default:
932      VIXL_UNREACHABLE();
933  }
934  return 0;
935}
936
937
938void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
939  if (IsPCRelAddressing()) {
940    SetPCRelImmTarget(target);
941  } else {
942    SetBranchImmTarget(target);
943  }
944}
945
946
947void Instruction::SetPCRelImmTarget(const Instruction* target) {
948  ptrdiff_t imm21;
949  if ((Mask(PCRelAddressingMask) == ADR)) {
950    imm21 = target - this;
951  } else {
952    VIXL_ASSERT(Mask(PCRelAddressingMask) == ADRP);
953    uintptr_t this_page = reinterpret_cast<uintptr_t>(this) / kPageSize;
954    uintptr_t target_page = reinterpret_cast<uintptr_t>(target) / kPageSize;
955    imm21 = target_page - this_page;
956  }
957  Instr imm = Assembler::ImmPCRelAddress(static_cast<int32_t>(imm21));
958
959  SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
960}
961
962
963void Instruction::SetBranchImmTarget(const Instruction* target) {
964  VIXL_ASSERT(((target - this) & 3) == 0);
965  Instr branch_imm = 0;
966  uint32_t imm_mask = 0;
967  int offset = static_cast<int>((target - this) >> kInstructionSizeLog2);
968  switch (GetBranchType()) {
969    case CondBranchType: {
970      branch_imm = Assembler::ImmCondBranch(offset);
971      imm_mask = ImmCondBranch_mask;
972      break;
973    }
974    case UncondBranchType: {
975      branch_imm = Assembler::ImmUncondBranch(offset);
976      imm_mask = ImmUncondBranch_mask;
977      break;
978    }
979    case CompareBranchType: {
980      branch_imm = Assembler::ImmCmpBranch(offset);
981      imm_mask = ImmCmpBranch_mask;
982      break;
983    }
984    case TestBranchType: {
985      branch_imm = Assembler::ImmTestBranch(offset);
986      imm_mask = ImmTestBranch_mask;
987      break;
988    }
989    default:
990      VIXL_UNREACHABLE();
991  }
992  SetInstructionBits(Mask(~imm_mask) | branch_imm);
993}
994
995
996void Instruction::SetImmLLiteral(const Instruction* source) {
997  VIXL_ASSERT(IsWordAligned(source));
998  ptrdiff_t offset = (source - this) >> kLiteralEntrySizeLog2;
999  Instr imm = Assembler::ImmLLiteral(static_cast<int>(offset));
1000  Instr mask = ImmLLiteral_mask;
1001
1002  SetInstructionBits(Mask(~mask) | imm);
1003}
1004
1005
1006VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
1007  switch (vform) {
1008    case kFormat8H:
1009      return kFormat8B;
1010    case kFormat4S:
1011      return kFormat4H;
1012    case kFormat2D:
1013      return kFormat2S;
1014    case kFormatH:
1015      return kFormatB;
1016    case kFormatS:
1017      return kFormatH;
1018    case kFormatD:
1019      return kFormatS;
1020    case kFormatVnH:
1021      return kFormatVnB;
1022    case kFormatVnS:
1023      return kFormatVnH;
1024    case kFormatVnD:
1025      return kFormatVnS;
1026    default:
1027      VIXL_UNREACHABLE();
1028      return kFormatUndefined;
1029  }
1030}
1031
1032
1033VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
1034  switch (vform) {
1035    case kFormat8B:
1036      return kFormat8H;
1037    case kFormat4H:
1038      return kFormat4S;
1039    case kFormat2S:
1040      return kFormat2D;
1041    case kFormatB:
1042      return kFormatH;
1043    case kFormatH:
1044      return kFormatS;
1045    case kFormatS:
1046      return kFormatD;
1047    case kFormatVnB:
1048      return kFormatVnH;
1049    case kFormatVnH:
1050      return kFormatVnS;
1051    case kFormatVnS:
1052      return kFormatVnD;
1053    default:
1054      VIXL_UNREACHABLE();
1055      return kFormatUndefined;
1056  }
1057}
1058
1059
1060VectorFormat VectorFormatFillQ(VectorFormat vform) {
1061  switch (vform) {
1062    case kFormatB:
1063    case kFormat8B:
1064    case kFormat16B:
1065      return kFormat16B;
1066    case kFormatH:
1067    case kFormat4H:
1068    case kFormat8H:
1069      return kFormat8H;
1070    case kFormatS:
1071    case kFormat2S:
1072    case kFormat4S:
1073      return kFormat4S;
1074    case kFormatD:
1075    case kFormat1D:
1076    case kFormat2D:
1077      return kFormat2D;
1078    default:
1079      VIXL_UNREACHABLE();
1080      return kFormatUndefined;
1081  }
1082}
1083
1084VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
1085  switch (vform) {
1086    case kFormat4H:
1087      return kFormat8B;
1088    case kFormat8H:
1089      return kFormat16B;
1090    case kFormat2S:
1091      return kFormat4H;
1092    case kFormat4S:
1093      return kFormat8H;
1094    case kFormat1D:
1095      return kFormat2S;
1096    case kFormat2D:
1097      return kFormat4S;
1098    case kFormatVnH:
1099      return kFormatVnB;
1100    case kFormatVnS:
1101      return kFormatVnH;
1102    case kFormatVnD:
1103      return kFormatVnS;
1104    default:
1105      VIXL_UNREACHABLE();
1106      return kFormatUndefined;
1107  }
1108}
1109
1110VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
1111  VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
1112  switch (vform) {
1113    case kFormat8B:
1114      return kFormat16B;
1115    case kFormat4H:
1116      return kFormat8H;
1117    case kFormat2S:
1118      return kFormat4S;
1119    default:
1120      VIXL_UNREACHABLE();
1121      return kFormatUndefined;
1122  }
1123}
1124
1125
1126VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
1127  VIXL_ASSERT(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
1128  switch (vform) {
1129    case kFormat16B:
1130      return kFormat8B;
1131    case kFormat8H:
1132      return kFormat4H;
1133    case kFormat4S:
1134      return kFormat2S;
1135    default:
1136      VIXL_UNREACHABLE();
1137      return kFormatUndefined;
1138  }
1139}
1140
1141
1142VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits) {
1143  switch (lane_size_in_bits) {
1144    case 8:
1145      return kFormatB;
1146    case 16:
1147      return kFormatH;
1148    case 32:
1149      return kFormatS;
1150    case 64:
1151      return kFormatD;
1152    default:
1153      VIXL_UNREACHABLE();
1154      return kFormatUndefined;
1155  }
1156}
1157
1158
1159bool IsSVEFormat(VectorFormat vform) {
1160  switch (vform) {
1161    case kFormatVnB:
1162    case kFormatVnH:
1163    case kFormatVnS:
1164    case kFormatVnD:
1165    case kFormatVnQ:
1166    case kFormatVnO:
1167      return true;
1168    default:
1169      return false;
1170  }
1171}
1172
1173
1174VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes) {
1175  switch (lane_size_in_bytes) {
1176    case 1:
1177      return kFormatVnB;
1178    case 2:
1179      return kFormatVnH;
1180    case 4:
1181      return kFormatVnS;
1182    case 8:
1183      return kFormatVnD;
1184    case 16:
1185      return kFormatVnQ;
1186    default:
1187      VIXL_UNREACHABLE();
1188      return kFormatUndefined;
1189  }
1190}
1191
1192
1193VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits) {
1194  switch (lane_size_in_bits) {
1195    case 8:
1196    case 16:
1197    case 32:
1198    case 64:
1199    case 128:
1200      return SVEFormatFromLaneSizeInBytes(lane_size_in_bits / kBitsPerByte);
1201    default:
1202      VIXL_UNREACHABLE();
1203      return kFormatUndefined;
1204  }
1205}
1206
1207
1208VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2) {
1209  switch (lane_size_in_bytes_log2) {
1210    case 0:
1211    case 1:
1212    case 2:
1213    case 3:
1214    case 4:
1215      return SVEFormatFromLaneSizeInBytes(1 << lane_size_in_bytes_log2);
1216    default:
1217      VIXL_UNREACHABLE();
1218      return kFormatUndefined;
1219  }
1220}
1221
1222
1223VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
1224  return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1225}
1226
1227
1228unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
1229  VIXL_ASSERT(vform != kFormatUndefined);
1230  VIXL_ASSERT(!IsSVEFormat(vform));
1231  switch (vform) {
1232    case kFormatB:
1233      return kBRegSize;
1234    case kFormatH:
1235      return kHRegSize;
1236    case kFormatS:
1237    case kFormat2H:
1238      return kSRegSize;
1239    case kFormatD:
1240    case kFormat8B:
1241    case kFormat4H:
1242    case kFormat2S:
1243    case kFormat1D:
1244      return kDRegSize;
1245    case kFormat16B:
1246    case kFormat8H:
1247    case kFormat4S:
1248    case kFormat2D:
1249      return kQRegSize;
1250    default:
1251      VIXL_UNREACHABLE();
1252      return 0;
1253  }
1254}
1255
1256
1257unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
1258  return RegisterSizeInBitsFromFormat(vform) / 8;
1259}
1260
1261
1262unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
1263  VIXL_ASSERT(vform != kFormatUndefined);
1264  switch (vform) {
1265    case kFormatB:
1266    case kFormat8B:
1267    case kFormat16B:
1268    case kFormatVnB:
1269      return 8;
1270    case kFormatH:
1271    case kFormat2H:
1272    case kFormat4H:
1273    case kFormat8H:
1274    case kFormatVnH:
1275      return 16;
1276    case kFormatS:
1277    case kFormat2S:
1278    case kFormat4S:
1279    case kFormatVnS:
1280      return 32;
1281    case kFormatD:
1282    case kFormat1D:
1283    case kFormat2D:
1284    case kFormatVnD:
1285      return 64;
1286    case kFormatVnQ:
1287      return 128;
1288    case kFormatVnO:
1289      return 256;
1290    default:
1291      VIXL_UNREACHABLE();
1292      return 0;
1293  }
1294}
1295
1296
1297int LaneSizeInBytesFromFormat(VectorFormat vform) {
1298  return LaneSizeInBitsFromFormat(vform) / 8;
1299}
1300
1301
1302int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
1303  VIXL_ASSERT(vform != kFormatUndefined);
1304  switch (vform) {
1305    case kFormatB:
1306    case kFormat8B:
1307    case kFormat16B:
1308    case kFormatVnB:
1309      return 0;
1310    case kFormatH:
1311    case kFormat2H:
1312    case kFormat4H:
1313    case kFormat8H:
1314    case kFormatVnH:
1315      return 1;
1316    case kFormatS:
1317    case kFormat2S:
1318    case kFormat4S:
1319    case kFormatVnS:
1320      return 2;
1321    case kFormatD:
1322    case kFormat1D:
1323    case kFormat2D:
1324    case kFormatVnD:
1325      return 3;
1326    case kFormatVnQ:
1327      return 4;
1328    default:
1329      VIXL_UNREACHABLE();
1330      return 0;
1331  }
1332}
1333
1334
1335int LaneCountFromFormat(VectorFormat vform) {
1336  VIXL_ASSERT(vform != kFormatUndefined);
1337  switch (vform) {
1338    case kFormat16B:
1339      return 16;
1340    case kFormat8B:
1341    case kFormat8H:
1342      return 8;
1343    case kFormat4H:
1344    case kFormat4S:
1345      return 4;
1346    case kFormat2H:
1347    case kFormat2S:
1348    case kFormat2D:
1349      return 2;
1350    case kFormat1D:
1351    case kFormatB:
1352    case kFormatH:
1353    case kFormatS:
1354    case kFormatD:
1355      return 1;
1356    default:
1357      VIXL_UNREACHABLE();
1358      return 0;
1359  }
1360}
1361
1362
1363int MaxLaneCountFromFormat(VectorFormat vform) {
1364  VIXL_ASSERT(vform != kFormatUndefined);
1365  switch (vform) {
1366    case kFormatB:
1367    case kFormat8B:
1368    case kFormat16B:
1369      return 16;
1370    case kFormatH:
1371    case kFormat4H:
1372    case kFormat8H:
1373      return 8;
1374    case kFormatS:
1375    case kFormat2S:
1376    case kFormat4S:
1377      return 4;
1378    case kFormatD:
1379    case kFormat1D:
1380    case kFormat2D:
1381      return 2;
1382    default:
1383      VIXL_UNREACHABLE();
1384      return 0;
1385  }
1386}
1387
1388
1389// Does 'vform' indicate a vector format or a scalar format?
1390bool IsVectorFormat(VectorFormat vform) {
1391  VIXL_ASSERT(vform != kFormatUndefined);
1392  switch (vform) {
1393    case kFormatB:
1394    case kFormatH:
1395    case kFormatS:
1396    case kFormatD:
1397      return false;
1398    default:
1399      return true;
1400  }
1401}
1402
1403
1404int64_t MaxIntFromFormat(VectorFormat vform) {
1405  int lane_size = LaneSizeInBitsFromFormat(vform);
1406  return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
1407}
1408
1409
1410int64_t MinIntFromFormat(VectorFormat vform) {
1411  return -MaxIntFromFormat(vform) - 1;
1412}
1413
1414
1415uint64_t MaxUintFromFormat(VectorFormat vform) {
1416  return GetUintMask(LaneSizeInBitsFromFormat(vform));
1417}
1418
1419}  // namespace aarch64
1420}  // namespace vixl
1421