• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Get the register and index for NEON indexed multiplies.
GetNEONMulRmAndIndex() const607 std::pair<int, int> Instruction::GetNEONMulRmAndIndex() const {
608   int reg_code = GetRm();
609   int index = (GetNEONH() << 2) | (GetNEONL() << 1) | GetNEONM();
610   switch (GetNEONSize()) {
611     case 0:  // FP H-sized elements.
612     case 1:  // Integer H-sized elements.
613       // 4-bit Rm, 3-bit index.
614       reg_code &= 0xf;
615       break;
616     case 2:  // S-sized elements.
617       // 5-bit Rm, 2-bit index.
618       index >>= 1;
619       break;
620     case 3:  // FP D-sized elements.
621       // 5-bit Rm, 1-bit index.
622       index >>= 2;
623       break;
624   }
625   return std::make_pair(reg_code, index);
626 }
627 
628 // Logical immediates can't encode zero, so a return value of zero is used to
629 // indicate a failure case. Specifically, where the constraints on imm_s are
630 // not met.
GetImmLogical() const631 uint64_t Instruction::GetImmLogical() const {
632   unsigned reg_size = GetSixtyFourBits() ? kXRegSize : kWRegSize;
633   int32_t n = GetBitN();
634   int32_t imm_s = GetImmSetBits();
635   int32_t imm_r = GetImmRotate();
636   return DecodeImmBitMask(n, imm_s, imm_r, reg_size);
637 }
638 
639 // Logical immediates can't encode zero, so a return value of zero is used to
640 // indicate a failure case. Specifically, where the constraints on imm_s are
641 // not met.
GetSVEImmLogical() const642 uint64_t Instruction::GetSVEImmLogical() const {
643   int n = GetSVEBitN();
644   int imm_s = GetSVEImmSetBits();
645   int imm_r = GetSVEImmRotate();
646   int lane_size_in_bytes_log2 = GetSVEBitwiseImmLaneSizeInBytesLog2();
647   switch (lane_size_in_bytes_log2) {
648     case kDRegSizeInBytesLog2:
649     case kSRegSizeInBytesLog2:
650     case kHRegSizeInBytesLog2:
651     case kBRegSizeInBytesLog2: {
652       int lane_size_in_bits = 1 << (lane_size_in_bytes_log2 + 3);
653       return DecodeImmBitMask(n, imm_s, imm_r, lane_size_in_bits);
654     }
655     default:
656       return 0;
657   }
658 }
659 
GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const660 std::pair<int, int> Instruction::GetSVEImmShiftAndLaneSizeLog2(
661     bool is_predicated) const {
662   Instr tsize =
663       is_predicated ? ExtractBits<0x00C00300>() : ExtractBits<0x00D80000>();
664   Instr imm_3 =
665       is_predicated ? ExtractBits<0x000000E0>() : ExtractBits<0x00070000>();
666   if (tsize == 0) {
667     // The bit field `tsize` means undefined if it is zero, so return a
668     // convenience value kWMinInt to indicate a failure case.
669     return std::make_pair(kWMinInt, kWMinInt);
670   }
671 
672   int lane_size_in_bytes_log_2 = 32 - CountLeadingZeros(tsize, 32) - 1;
673   int esize = (1 << lane_size_in_bytes_log_2) * kBitsPerByte;
674   int shift = (2 * esize) - ((tsize << 3) | imm_3);
675   return std::make_pair(shift, lane_size_in_bytes_log_2);
676 }
677 
GetSVEMsizeFromDtype(bool is_signed,int dtype_h_lsb) const678 int Instruction::GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb) const {
679   Instr dtype_h = ExtractBits(dtype_h_lsb + 1, dtype_h_lsb);
680   if (is_signed) {
681     dtype_h = dtype_h ^ 0x3;
682   }
683   return dtype_h;
684 }
685 
GetSVEEsizeFromDtype(bool is_signed,int dtype_l_lsb) const686 int Instruction::GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb) const {
687   Instr dtype_l = ExtractBits(dtype_l_lsb + 1, dtype_l_lsb);
688   if (is_signed) {
689     dtype_l = dtype_l ^ 0x3;
690   }
691   return dtype_l;
692 }
693 
GetSVEBitwiseImmLaneSizeInBytesLog2() const694 int Instruction::GetSVEBitwiseImmLaneSizeInBytesLog2() const {
695   int n = GetSVEBitN();
696   int imm_s = GetSVEImmSetBits();
697   unsigned type_bitset =
698       (n << SVEImmSetBits_width) | (~imm_s & GetUintMask(SVEImmSetBits_width));
699 
700   // An lane size is constructed from the n and imm_s bits according to
701   // the following table:
702   //
703   // N   imms   size
704   // 0  0xxxxx   32
705   // 0  10xxxx   16
706   // 0  110xxx    8
707   // 0  1110xx    8
708   // 0  11110x    8
709   // 1  xxxxxx   64
710 
711   if (type_bitset == 0) {
712     // Bail out early since `HighestSetBitPosition` doesn't accept zero
713     // value input.
714     return -1;
715   }
716 
717   switch (HighestSetBitPosition(type_bitset)) {
718     case 6:
719       return kDRegSizeInBytesLog2;
720     case 5:
721       return kSRegSizeInBytesLog2;
722     case 4:
723       return kHRegSizeInBytesLog2;
724     case 3:
725     case 2:
726     case 1:
727       return kBRegSizeInBytesLog2;
728     default:
729       // RESERVED encoding.
730       return -1;
731   }
732 }
733 
GetSVEExtractImmediate() const734 int Instruction::GetSVEExtractImmediate() const {
735   const int imm8h_mask = 0x001F0000;
736   const int imm8l_mask = 0x00001C00;
737   return ExtractBits<imm8h_mask | imm8l_mask>();
738 }
739 
DecodeImmBitMask(int32_t n,int32_t imm_s,int32_t imm_r,int32_t size) const740 uint64_t Instruction::DecodeImmBitMask(int32_t n,
741                                        int32_t imm_s,
742                                        int32_t imm_r,
743                                        int32_t size) const {
744   // An integer is constructed from the n, imm_s and imm_r bits according to
745   // the following table:
746   //
747   //  N   imms    immr    size        S             R
748   //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
749   //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
750   //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
751   //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
752   //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
753   //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
754   // (s bits must not be all set)
755   //
756   // A pattern is constructed of size bits, where the least significant S+1
757   // bits are set. The pattern is rotated right by R, and repeated across a
758   // 32 or 64-bit value, depending on destination register width.
759   //
760 
761   if (n == 1) {
762     if (imm_s == 0x3f) {
763       return 0;
764     }
765     uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
766     return RotateRight(bits, imm_r, 64);
767   } else {
768     if ((imm_s >> 1) == 0x1f) {
769       return 0;
770     }
771     for (int width = 0x20; width >= 0x2; width >>= 1) {
772       if ((imm_s & width) == 0) {
773         int mask = width - 1;
774         if ((imm_s & mask) == mask) {
775           return 0;
776         }
777         uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
778         return RepeatBitsAcrossReg(size,
779                                    RotateRight(bits, imm_r & mask, width),
780                                    width);
781       }
782     }
783   }
784   VIXL_UNREACHABLE();
785   return 0;
786 }
787 
788 
GetImmNEONabcdefgh() const789 uint32_t Instruction::GetImmNEONabcdefgh() const {
790   return GetImmNEONabc() << 5 | GetImmNEONdefgh();
791 }
792 
793 
Imm8ToFloat16(uint32_t imm8)794 Float16 Instruction::Imm8ToFloat16(uint32_t imm8) {
795   // Imm8: abcdefgh (8 bits)
796   // Half: aBbb.cdef.gh00.0000 (16 bits)
797   // where B is b ^ 1
798   uint32_t bits = imm8;
799   uint16_t bit7 = (bits >> 7) & 0x1;
800   uint16_t bit6 = (bits >> 6) & 0x1;
801   uint16_t bit5_to_0 = bits & 0x3f;
802   uint16_t result = (bit7 << 15) | ((4 - bit6) << 12) | (bit5_to_0 << 6);
803   return RawbitsToFloat16(result);
804 }
805 
806 
Imm8ToFP32(uint32_t imm8)807 float Instruction::Imm8ToFP32(uint32_t imm8) {
808   // Imm8: abcdefgh (8 bits)
809   // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
810   // where B is b ^ 1
811   uint32_t bits = imm8;
812   uint32_t bit7 = (bits >> 7) & 0x1;
813   uint32_t bit6 = (bits >> 6) & 0x1;
814   uint32_t bit5_to_0 = bits & 0x3f;
815   uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
816 
817   return RawbitsToFloat(result);
818 }
819 
820 
GetImmFP16() const821 Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
822 
823 
GetImmFP32() const824 float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
825 
826 
Imm8ToFP64(uint32_t imm8)827 double Instruction::Imm8ToFP64(uint32_t imm8) {
828   // Imm8: abcdefgh (8 bits)
829   // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
830   //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
831   // where B is b ^ 1
832   uint32_t bits = imm8;
833   uint64_t bit7 = (bits >> 7) & 0x1;
834   uint64_t bit6 = (bits >> 6) & 0x1;
835   uint64_t bit5_to_0 = bits & 0x3f;
836   uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
837 
838   return RawbitsToDouble(result);
839 }
840 
841 
GetImmFP64() const842 double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
843 
844 
GetImmNEONFP16() const845 Float16 Instruction::GetImmNEONFP16() const {
846   return Imm8ToFloat16(GetImmNEONabcdefgh());
847 }
848 
849 
GetImmNEONFP32() const850 float Instruction::GetImmNEONFP32() const {
851   return Imm8ToFP32(GetImmNEONabcdefgh());
852 }
853 
854 
GetImmNEONFP64() const855 double Instruction::GetImmNEONFP64() const {
856   return Imm8ToFP64(GetImmNEONabcdefgh());
857 }
858 
859 
CalcLSDataSize(LoadStoreOp op)860 unsigned CalcLSDataSize(LoadStoreOp op) {
861   VIXL_ASSERT((LSSize_offset + LSSize_width) == (kInstructionSize * 8));
862   unsigned size = static_cast<Instr>(op) >> LSSize_offset;
863   if ((op & LSVector_mask) != 0) {
864     // Vector register memory operations encode the access size in the "size"
865     // and "opc" fields.
866     if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
867       size = kQRegSizeInBytesLog2;
868     }
869   }
870   return size;
871 }
872 
873 
CalcLSPairDataSize(LoadStorePairOp op)874 unsigned CalcLSPairDataSize(LoadStorePairOp op) {
875   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
876   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
877   switch (op) {
878     case STP_q:
879     case LDP_q:
880       return kQRegSizeInBytesLog2;
881     case STP_x:
882     case LDP_x:
883     case STP_d:
884     case LDP_d:
885       return kXRegSizeInBytesLog2;
886     default:
887       return kWRegSizeInBytesLog2;
888   }
889 }
890 
891 
GetImmBranchRangeBitwidth(ImmBranchType branch_type)892 int Instruction::GetImmBranchRangeBitwidth(ImmBranchType branch_type) {
893   switch (branch_type) {
894     case UncondBranchType:
895       return ImmUncondBranch_width;
896     case CondBranchType:
897       return ImmCondBranch_width;
898     case CompareBranchType:
899       return ImmCmpBranch_width;
900     case TestBranchType:
901       return ImmTestBranch_width;
902     default:
903       VIXL_UNREACHABLE();
904       return 0;
905   }
906 }
907 
908 
GetImmBranchForwardRange(ImmBranchType branch_type)909 int32_t Instruction::GetImmBranchForwardRange(ImmBranchType branch_type) {
910   int32_t encoded_max = 1 << (GetImmBranchRangeBitwidth(branch_type) - 1);
911   return encoded_max * kInstructionSize;
912 }
913 
914 
IsValidImmPCOffset(ImmBranchType branch_type,int64_t offset)915 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
916                                      int64_t offset) {
917   return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
918 }
919 
920 
GetImmPCOffsetTarget() const921 const Instruction* Instruction::GetImmPCOffsetTarget() const {
922   const Instruction* base = this;
923   ptrdiff_t offset;
924   if (IsPCRelAddressing()) {
925     // ADR and ADRP.
926     offset = GetImmPCRel();
927     if (Mask(PCRelAddressingMask) == ADRP) {
928       base = AlignDown(base, kPageSize);
929       offset *= kPageSize;
930     } else {
931       VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
932     }
933   } else {
934     // All PC-relative branches.
935     VIXL_ASSERT(GetBranchType() != UnknownBranchType);
936     // Relative branch offsets are instruction-size-aligned.
937     offset = GetImmBranch() * static_cast<int>(kInstructionSize);
938   }
939   return base + offset;
940 }
941 
942 
GetImmBranch() const943 int Instruction::GetImmBranch() const {
944   switch (GetBranchType()) {
945     case CondBranchType:
946       return GetImmCondBranch();
947     case UncondBranchType:
948       return GetImmUncondBranch();
949     case CompareBranchType:
950       return GetImmCmpBranch();
951     case TestBranchType:
952       return GetImmTestBranch();
953     default:
954       VIXL_UNREACHABLE();
955   }
956   return 0;
957 }
958 
959 
SetImmPCOffsetTarget(const Instruction * target)960 void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
961   if (IsPCRelAddressing()) {
962     SetPCRelImmTarget(target);
963   } else {
964     SetBranchImmTarget(target);
965   }
966 }
967 
968 
SetPCRelImmTarget(const Instruction * target)969 void Instruction::SetPCRelImmTarget(const Instruction* target) {
970   ptrdiff_t imm21;
971   if ((Mask(PCRelAddressingMask) == ADR)) {
972     imm21 = target - this;
973   } else {
974     VIXL_ASSERT(Mask(PCRelAddressingMask) == ADRP);
975     uintptr_t this_page = reinterpret_cast<uintptr_t>(this) / kPageSize;
976     uintptr_t target_page = reinterpret_cast<uintptr_t>(target) / kPageSize;
977     imm21 = target_page - this_page;
978   }
979   Instr imm = Assembler::ImmPCRelAddress(static_cast<int32_t>(imm21));
980 
981   SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
982 }
983 
984 
SetBranchImmTarget(const Instruction * target)985 void Instruction::SetBranchImmTarget(const Instruction* target) {
986   VIXL_ASSERT(((target - this) & 3) == 0);
987   Instr branch_imm = 0;
988   uint32_t imm_mask = 0;
989   int offset = static_cast<int>((target - this) >> kInstructionSizeLog2);
990   switch (GetBranchType()) {
991     case CondBranchType: {
992       branch_imm = Assembler::ImmCondBranch(offset);
993       imm_mask = ImmCondBranch_mask;
994       break;
995     }
996     case UncondBranchType: {
997       branch_imm = Assembler::ImmUncondBranch(offset);
998       imm_mask = ImmUncondBranch_mask;
999       break;
1000     }
1001     case CompareBranchType: {
1002       branch_imm = Assembler::ImmCmpBranch(offset);
1003       imm_mask = ImmCmpBranch_mask;
1004       break;
1005     }
1006     case TestBranchType: {
1007       branch_imm = Assembler::ImmTestBranch(offset);
1008       imm_mask = ImmTestBranch_mask;
1009       break;
1010     }
1011     default:
1012       VIXL_UNREACHABLE();
1013   }
1014   SetInstructionBits(Mask(~imm_mask) | branch_imm);
1015 }
1016 
1017 
SetImmLLiteral(const Instruction * source)1018 void Instruction::SetImmLLiteral(const Instruction* source) {
1019   VIXL_ASSERT(IsWordAligned(source));
1020   ptrdiff_t offset = (source - this) >> kLiteralEntrySizeLog2;
1021   Instr imm = Assembler::ImmLLiteral(static_cast<int>(offset));
1022   Instr mask = ImmLLiteral_mask;
1023 
1024   SetInstructionBits(Mask(~mask) | imm);
1025 }
1026 
1027 
VectorFormatHalfWidth(VectorFormat vform)1028 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
1029   switch (vform) {
1030     case kFormat8H:
1031       return kFormat8B;
1032     case kFormat4S:
1033       return kFormat4H;
1034     case kFormat2D:
1035       return kFormat2S;
1036     case kFormat1Q:
1037       return kFormat1D;
1038     case kFormatH:
1039       return kFormatB;
1040     case kFormatS:
1041       return kFormatH;
1042     case kFormatD:
1043       return kFormatS;
1044     case kFormatVnH:
1045       return kFormatVnB;
1046     case kFormatVnS:
1047       return kFormatVnH;
1048     case kFormatVnD:
1049       return kFormatVnS;
1050     case kFormatVnQ:
1051       return kFormatVnD;
1052     default:
1053       VIXL_UNREACHABLE();
1054       return kFormatUndefined;
1055   }
1056 }
1057 
1058 
VectorFormatDoubleWidth(VectorFormat vform)1059 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
1060   switch (vform) {
1061     case kFormat8B:
1062       return kFormat8H;
1063     case kFormat4H:
1064       return kFormat4S;
1065     case kFormat2S:
1066       return kFormat2D;
1067     case kFormatB:
1068       return kFormatH;
1069     case kFormatH:
1070       return kFormatS;
1071     case kFormatS:
1072       return kFormatD;
1073     case kFormatVnB:
1074       return kFormatVnH;
1075     case kFormatVnH:
1076       return kFormatVnS;
1077     case kFormatVnS:
1078       return kFormatVnD;
1079     default:
1080       VIXL_UNREACHABLE();
1081       return kFormatUndefined;
1082   }
1083 }
1084 
1085 
VectorFormatFillQ(VectorFormat vform)1086 VectorFormat VectorFormatFillQ(VectorFormat vform) {
1087   switch (vform) {
1088     case kFormatB:
1089     case kFormat8B:
1090     case kFormat16B:
1091       return kFormat16B;
1092     case kFormatH:
1093     case kFormat4H:
1094     case kFormat8H:
1095       return kFormat8H;
1096     case kFormatS:
1097     case kFormat2S:
1098     case kFormat4S:
1099       return kFormat4S;
1100     case kFormatD:
1101     case kFormat1D:
1102     case kFormat2D:
1103       return kFormat2D;
1104     default:
1105       VIXL_UNREACHABLE();
1106       return kFormatUndefined;
1107   }
1108 }
1109 
VectorFormatHalfWidthDoubleLanes(VectorFormat vform)1110 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
1111   switch (vform) {
1112     case kFormat4H:
1113       return kFormat8B;
1114     case kFormat8H:
1115       return kFormat16B;
1116     case kFormat2S:
1117       return kFormat4H;
1118     case kFormat4S:
1119       return kFormat8H;
1120     case kFormat1D:
1121       return kFormat2S;
1122     case kFormat2D:
1123       return kFormat4S;
1124     case kFormat1Q:
1125       return kFormat2D;
1126     case kFormatVnH:
1127       return kFormatVnB;
1128     case kFormatVnS:
1129       return kFormatVnH;
1130     case kFormatVnD:
1131       return kFormatVnS;
1132     default:
1133       VIXL_UNREACHABLE();
1134       return kFormatUndefined;
1135   }
1136 }
1137 
VectorFormatDoubleLanes(VectorFormat vform)1138 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
1139   VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
1140   switch (vform) {
1141     case kFormat8B:
1142       return kFormat16B;
1143     case kFormat4H:
1144       return kFormat8H;
1145     case kFormat2S:
1146       return kFormat4S;
1147     default:
1148       VIXL_UNREACHABLE();
1149       return kFormatUndefined;
1150   }
1151 }
1152 
1153 
VectorFormatHalfLanes(VectorFormat vform)1154 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
1155   VIXL_ASSERT(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
1156   switch (vform) {
1157     case kFormat16B:
1158       return kFormat8B;
1159     case kFormat8H:
1160       return kFormat4H;
1161     case kFormat4S:
1162       return kFormat2S;
1163     default:
1164       VIXL_UNREACHABLE();
1165       return kFormatUndefined;
1166   }
1167 }
1168 
1169 
ScalarFormatFromLaneSize(int lane_size_in_bits)1170 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits) {
1171   switch (lane_size_in_bits) {
1172     case 8:
1173       return kFormatB;
1174     case 16:
1175       return kFormatH;
1176     case 32:
1177       return kFormatS;
1178     case 64:
1179       return kFormatD;
1180     default:
1181       VIXL_UNREACHABLE();
1182       return kFormatUndefined;
1183   }
1184 }
1185 
1186 
IsSVEFormat(VectorFormat vform)1187 bool IsSVEFormat(VectorFormat vform) {
1188   switch (vform) {
1189     case kFormatVnB:
1190     case kFormatVnH:
1191     case kFormatVnS:
1192     case kFormatVnD:
1193     case kFormatVnQ:
1194     case kFormatVnO:
1195       return true;
1196     default:
1197       return false;
1198   }
1199 }
1200 
1201 
SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes)1202 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes) {
1203   switch (lane_size_in_bytes) {
1204     case 1:
1205       return kFormatVnB;
1206     case 2:
1207       return kFormatVnH;
1208     case 4:
1209       return kFormatVnS;
1210     case 8:
1211       return kFormatVnD;
1212     case 16:
1213       return kFormatVnQ;
1214     default:
1215       VIXL_UNREACHABLE();
1216       return kFormatUndefined;
1217   }
1218 }
1219 
1220 
SVEFormatFromLaneSizeInBits(int lane_size_in_bits)1221 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits) {
1222   switch (lane_size_in_bits) {
1223     case 8:
1224     case 16:
1225     case 32:
1226     case 64:
1227     case 128:
1228       return SVEFormatFromLaneSizeInBytes(lane_size_in_bits / kBitsPerByte);
1229     default:
1230       VIXL_UNREACHABLE();
1231       return kFormatUndefined;
1232   }
1233 }
1234 
1235 
SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2)1236 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2) {
1237   switch (lane_size_in_bytes_log2) {
1238     case 0:
1239     case 1:
1240     case 2:
1241     case 3:
1242     case 4:
1243       return SVEFormatFromLaneSizeInBytes(1 << lane_size_in_bytes_log2);
1244     default:
1245       VIXL_UNREACHABLE();
1246       return kFormatUndefined;
1247   }
1248 }
1249 
1250 
ScalarFormatFromFormat(VectorFormat vform)1251 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
1252   return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1253 }
1254 
1255 
RegisterSizeInBitsFromFormat(VectorFormat vform)1256 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
1257   VIXL_ASSERT(vform != kFormatUndefined);
1258   VIXL_ASSERT(!IsSVEFormat(vform));
1259   switch (vform) {
1260     case kFormatB:
1261       return kBRegSize;
1262     case kFormatH:
1263       return kHRegSize;
1264     case kFormatS:
1265     case kFormat2H:
1266       return kSRegSize;
1267     case kFormatD:
1268     case kFormat8B:
1269     case kFormat4H:
1270     case kFormat2S:
1271     case kFormat1D:
1272       return kDRegSize;
1273     case kFormat16B:
1274     case kFormat8H:
1275     case kFormat4S:
1276     case kFormat2D:
1277     case kFormat1Q:
1278       return kQRegSize;
1279     default:
1280       VIXL_UNREACHABLE();
1281       return 0;
1282   }
1283 }
1284 
1285 
RegisterSizeInBytesFromFormat(VectorFormat vform)1286 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
1287   return RegisterSizeInBitsFromFormat(vform) / 8;
1288 }
1289 
1290 
LaneSizeInBitsFromFormat(VectorFormat vform)1291 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
1292   VIXL_ASSERT(vform != kFormatUndefined);
1293   switch (vform) {
1294     case kFormatB:
1295     case kFormat8B:
1296     case kFormat16B:
1297     case kFormatVnB:
1298       return 8;
1299     case kFormatH:
1300     case kFormat2H:
1301     case kFormat4H:
1302     case kFormat8H:
1303     case kFormatVnH:
1304       return 16;
1305     case kFormatS:
1306     case kFormat2S:
1307     case kFormat4S:
1308     case kFormatVnS:
1309       return 32;
1310     case kFormatD:
1311     case kFormat1D:
1312     case kFormat2D:
1313     case kFormatVnD:
1314       return 64;
1315     case kFormat1Q:
1316     case kFormatVnQ:
1317       return 128;
1318     case kFormatVnO:
1319       return 256;
1320     default:
1321       VIXL_UNREACHABLE();
1322       return 0;
1323   }
1324 }
1325 
1326 
LaneSizeInBytesFromFormat(VectorFormat vform)1327 int LaneSizeInBytesFromFormat(VectorFormat vform) {
1328   return LaneSizeInBitsFromFormat(vform) / 8;
1329 }
1330 
1331 
LaneSizeInBytesLog2FromFormat(VectorFormat vform)1332 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
1333   VIXL_ASSERT(vform != kFormatUndefined);
1334   switch (vform) {
1335     case kFormatB:
1336     case kFormat8B:
1337     case kFormat16B:
1338     case kFormatVnB:
1339       return 0;
1340     case kFormatH:
1341     case kFormat2H:
1342     case kFormat4H:
1343     case kFormat8H:
1344     case kFormatVnH:
1345       return 1;
1346     case kFormatS:
1347     case kFormat2S:
1348     case kFormat4S:
1349     case kFormatVnS:
1350       return 2;
1351     case kFormatD:
1352     case kFormat1D:
1353     case kFormat2D:
1354     case kFormatVnD:
1355       return 3;
1356     case kFormatVnQ:
1357       return 4;
1358     default:
1359       VIXL_UNREACHABLE();
1360       return 0;
1361   }
1362 }
1363 
1364 
LaneCountFromFormat(VectorFormat vform)1365 int LaneCountFromFormat(VectorFormat vform) {
1366   VIXL_ASSERT(vform != kFormatUndefined);
1367   switch (vform) {
1368     case kFormat16B:
1369       return 16;
1370     case kFormat8B:
1371     case kFormat8H:
1372       return 8;
1373     case kFormat4H:
1374     case kFormat4S:
1375       return 4;
1376     case kFormat2H:
1377     case kFormat2S:
1378     case kFormat2D:
1379       return 2;
1380     case kFormat1D:
1381     case kFormat1Q:
1382     case kFormatB:
1383     case kFormatH:
1384     case kFormatS:
1385     case kFormatD:
1386       return 1;
1387     default:
1388       VIXL_UNREACHABLE();
1389       return 0;
1390   }
1391 }
1392 
1393 
MaxLaneCountFromFormat(VectorFormat vform)1394 int MaxLaneCountFromFormat(VectorFormat vform) {
1395   VIXL_ASSERT(vform != kFormatUndefined);
1396   switch (vform) {
1397     case kFormatB:
1398     case kFormat8B:
1399     case kFormat16B:
1400       return 16;
1401     case kFormatH:
1402     case kFormat4H:
1403     case kFormat8H:
1404       return 8;
1405     case kFormatS:
1406     case kFormat2S:
1407     case kFormat4S:
1408       return 4;
1409     case kFormatD:
1410     case kFormat1D:
1411     case kFormat2D:
1412       return 2;
1413     default:
1414       VIXL_UNREACHABLE();
1415       return 0;
1416   }
1417 }
1418 
1419 
1420 // Does 'vform' indicate a vector format or a scalar format?
IsVectorFormat(VectorFormat vform)1421 bool IsVectorFormat(VectorFormat vform) {
1422   VIXL_ASSERT(vform != kFormatUndefined);
1423   switch (vform) {
1424     case kFormatB:
1425     case kFormatH:
1426     case kFormatS:
1427     case kFormatD:
1428       return false;
1429     default:
1430       return true;
1431   }
1432 }
1433 
1434 
MaxIntFromFormat(VectorFormat vform)1435 int64_t MaxIntFromFormat(VectorFormat vform) {
1436   int lane_size = LaneSizeInBitsFromFormat(vform);
1437   return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
1438 }
1439 
1440 
MinIntFromFormat(VectorFormat vform)1441 int64_t MinIntFromFormat(VectorFormat vform) {
1442   return -MaxIntFromFormat(vform) - 1;
1443 }
1444 
1445 
MaxUintFromFormat(VectorFormat vform)1446 uint64_t MaxUintFromFormat(VectorFormat vform) {
1447   return GetUintMask(LaneSizeInBitsFromFormat(vform));
1448 }
1449 
1450 }  // namespace aarch64
1451 }  // namespace vixl
1452