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 
31 namespace vixl {
32 namespace aarch64 {
33 
RepeatBitsAcrossReg(unsigned reg_size, uint64_t value, unsigned width)34 static 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 
CanTakeSVEMovprfx(const char* form, const Instruction* movprfx) const48 bool Instruction::CanTakeSVEMovprfx(const char* form,
49                                     const Instruction* movprfx) const {
50   return CanTakeSVEMovprfx(Hash(form), movprfx);
51 }
52 
CanTakeSVEMovprfx(uint32_t form_hash, const Instruction* movprfx) const53 bool 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 
IsLoad() const485 bool 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 
IsStore() const517 bool 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 
GetSVEPermuteIndexAndLaneSizeLog2() const544 std::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>
GetSVEMulZmAndIndex() const557 std::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>
GetSVEMulLongZmAndIndex() const585 std::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.
GetImmLogical() const609 uint64_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.
GetSVEImmLogical() const620 uint64_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 
GetSVEImmShiftAndLaneSizeLog2( bool is_predicated) const638 std::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 
GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb) const656 int 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 
GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb) const664 int 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 
GetSVEBitwiseImmLaneSizeInBytesLog2() const672 int 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 
GetSVEExtractImmediate() const712 int Instruction::GetSVEExtractImmediate() const {
713   const int imm8h_mask = 0x001F0000;
714   const int imm8l_mask = 0x00001C00;
715   return ExtractBits<imm8h_mask | imm8l_mask>();
716 }
717 
DecodeImmBitMask(int32_t n, int32_t imm_s, int32_t imm_r, int32_t size) const718 uint64_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 
GetImmNEONabcdefgh() const767 uint32_t Instruction::GetImmNEONabcdefgh() const {
768   return GetImmNEONabc() << 5 | GetImmNEONdefgh();
769 }
770 
771 
Imm8ToFloat16(uint32_t imm8)772 Float16 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 
Imm8ToFP32(uint32_t imm8)785 float 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 
GetImmFP16() const799 Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
800 
801 
GetImmFP32() const802 float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
803 
804 
Imm8ToFP64(uint32_t imm8)805 double 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 
GetImmFP64() const820 double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
821 
822 
GetImmNEONFP16() const823 Float16 Instruction::GetImmNEONFP16() const {
824   return Imm8ToFloat16(GetImmNEONabcdefgh());
825 }
826 
827 
GetImmNEONFP32() const828 float Instruction::GetImmNEONFP32() const {
829   return Imm8ToFP32(GetImmNEONabcdefgh());
830 }
831 
832 
GetImmNEONFP64() const833 double Instruction::GetImmNEONFP64() const {
834   return Imm8ToFP64(GetImmNEONabcdefgh());
835 }
836 
837 
CalcLSDataSize(LoadStoreOp op)838 unsigned 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 
CalcLSPairDataSize(LoadStorePairOp op)852 unsigned 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 
GetImmBranchRangeBitwidth(ImmBranchType branch_type)870 int 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 
GetImmBranchForwardRange(ImmBranchType branch_type)887 int32_t Instruction::GetImmBranchForwardRange(ImmBranchType branch_type) {
888   int32_t encoded_max = 1 << (GetImmBranchRangeBitwidth(branch_type) - 1);
889   return encoded_max * kInstructionSize;
890 }
891 
892 
IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset)893 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
894                                      int64_t offset) {
895   return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
896 }
897 
898 
GetImmPCOffsetTarget() const899 const 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 
GetImmBranch() const921 int 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 
SetImmPCOffsetTarget(const Instruction* target)938 void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
939   if (IsPCRelAddressing()) {
940     SetPCRelImmTarget(target);
941   } else {
942     SetBranchImmTarget(target);
943   }
944 }
945 
946 
SetPCRelImmTarget(const Instruction* target)947 void 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 
SetBranchImmTarget(const Instruction* target)963 void 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 
SetImmLLiteral(const Instruction* source)996 void 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 
VectorFormatHalfWidth(VectorFormat vform)1006 VectorFormat 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 
VectorFormatDoubleWidth(VectorFormat vform)1033 VectorFormat 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 
VectorFormatFillQ(VectorFormat vform)1060 VectorFormat 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 
VectorFormatHalfWidthDoubleLanes(VectorFormat vform)1084 VectorFormat 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 
VectorFormatDoubleLanes(VectorFormat vform)1110 VectorFormat 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 
VectorFormatHalfLanes(VectorFormat vform)1126 VectorFormat 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 
ScalarFormatFromLaneSize(int lane_size_in_bits)1142 VectorFormat 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 
IsSVEFormat(VectorFormat vform)1159 bool 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 
SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes)1174 VectorFormat 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 
SVEFormatFromLaneSizeInBits(int lane_size_in_bits)1193 VectorFormat 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 
SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2)1208 VectorFormat 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 
ScalarFormatFromFormat(VectorFormat vform)1223 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
1224   return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1225 }
1226 
1227 
RegisterSizeInBitsFromFormat(VectorFormat vform)1228 unsigned 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 
RegisterSizeInBytesFromFormat(VectorFormat vform)1257 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
1258   return RegisterSizeInBitsFromFormat(vform) / 8;
1259 }
1260 
1261 
LaneSizeInBitsFromFormat(VectorFormat vform)1262 unsigned 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 
LaneSizeInBytesFromFormat(VectorFormat vform)1297 int LaneSizeInBytesFromFormat(VectorFormat vform) {
1298   return LaneSizeInBitsFromFormat(vform) / 8;
1299 }
1300 
1301 
LaneSizeInBytesLog2FromFormat(VectorFormat vform)1302 int 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 
LaneCountFromFormat(VectorFormat vform)1335 int 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 
MaxLaneCountFromFormat(VectorFormat vform)1363 int 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?
IsVectorFormat(VectorFormat vform)1390 bool 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 
MaxIntFromFormat(VectorFormat vform)1404 int64_t MaxIntFromFormat(VectorFormat vform) {
1405   int lane_size = LaneSizeInBitsFromFormat(vform);
1406   return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
1407 }
1408 
1409 
MinIntFromFormat(VectorFormat vform)1410 int64_t MinIntFromFormat(VectorFormat vform) {
1411   return -MaxIntFromFormat(vform) - 1;
1412 }
1413 
1414 
MaxUintFromFormat(VectorFormat vform)1415 uint64_t MaxUintFromFormat(VectorFormat vform) {
1416   return GetUintMask(LaneSizeInBitsFromFormat(vform));
1417 }
1418 
1419 }  // namespace aarch64
1420 }  // namespace vixl
1421