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