Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/vixl/src/aarch64/instructions-aarch64.cc
4261 views
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
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
48
bool Instruction::CanTakeSVEMovprfx(const char* form,
49
const Instruction* movprfx) const {
50
return CanTakeSVEMovprfx(Hash(form), movprfx);
51
}
52
53
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
485
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
517
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
544
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>
557
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>
585
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.
609
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.
620
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
638
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
656
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
664
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
672
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
712
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
718
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
767
uint32_t Instruction::GetImmNEONabcdefgh() const {
768
return GetImmNEONabc() << 5 | GetImmNEONdefgh();
769
}
770
771
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
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
799
Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
800
801
802
float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
803
804
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
820
double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
821
822
823
Float16 Instruction::GetImmNEONFP16() const {
824
return Imm8ToFloat16(GetImmNEONabcdefgh());
825
}
826
827
828
float Instruction::GetImmNEONFP32() const {
829
return Imm8ToFP32(GetImmNEONabcdefgh());
830
}
831
832
833
double Instruction::GetImmNEONFP64() const {
834
return Imm8ToFP64(GetImmNEONabcdefgh());
835
}
836
837
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
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
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
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
893
bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
894
int64_t offset) {
895
return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
896
}
897
898
899
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
921
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
938
void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
939
if (IsPCRelAddressing()) {
940
SetPCRelImmTarget(target);
941
} else {
942
SetBranchImmTarget(target);
943
}
944
}
945
946
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
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
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
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 kFormat1Q:
1015
return kFormat1D;
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
default:
1029
VIXL_UNREACHABLE();
1030
return kFormatUndefined;
1031
}
1032
}
1033
1034
1035
VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
1036
switch (vform) {
1037
case kFormat8B:
1038
return kFormat8H;
1039
case kFormat4H:
1040
return kFormat4S;
1041
case kFormat2S:
1042
return kFormat2D;
1043
case kFormatB:
1044
return kFormatH;
1045
case kFormatH:
1046
return kFormatS;
1047
case kFormatS:
1048
return kFormatD;
1049
case kFormatVnB:
1050
return kFormatVnH;
1051
case kFormatVnH:
1052
return kFormatVnS;
1053
case kFormatVnS:
1054
return kFormatVnD;
1055
default:
1056
VIXL_UNREACHABLE();
1057
return kFormatUndefined;
1058
}
1059
}
1060
1061
1062
VectorFormat VectorFormatFillQ(VectorFormat vform) {
1063
switch (vform) {
1064
case kFormatB:
1065
case kFormat8B:
1066
case kFormat16B:
1067
return kFormat16B;
1068
case kFormatH:
1069
case kFormat4H:
1070
case kFormat8H:
1071
return kFormat8H;
1072
case kFormatS:
1073
case kFormat2S:
1074
case kFormat4S:
1075
return kFormat4S;
1076
case kFormatD:
1077
case kFormat1D:
1078
case kFormat2D:
1079
return kFormat2D;
1080
default:
1081
VIXL_UNREACHABLE();
1082
return kFormatUndefined;
1083
}
1084
}
1085
1086
VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
1087
switch (vform) {
1088
case kFormat4H:
1089
return kFormat8B;
1090
case kFormat8H:
1091
return kFormat16B;
1092
case kFormat2S:
1093
return kFormat4H;
1094
case kFormat4S:
1095
return kFormat8H;
1096
case kFormat1D:
1097
return kFormat2S;
1098
case kFormat2D:
1099
return kFormat4S;
1100
case kFormat1Q:
1101
return kFormat2D;
1102
case kFormatVnH:
1103
return kFormatVnB;
1104
case kFormatVnS:
1105
return kFormatVnH;
1106
case kFormatVnD:
1107
return kFormatVnS;
1108
default:
1109
VIXL_UNREACHABLE();
1110
return kFormatUndefined;
1111
}
1112
}
1113
1114
VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
1115
VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
1116
switch (vform) {
1117
case kFormat8B:
1118
return kFormat16B;
1119
case kFormat4H:
1120
return kFormat8H;
1121
case kFormat2S:
1122
return kFormat4S;
1123
default:
1124
VIXL_UNREACHABLE();
1125
return kFormatUndefined;
1126
}
1127
}
1128
1129
1130
VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
1131
VIXL_ASSERT(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
1132
switch (vform) {
1133
case kFormat16B:
1134
return kFormat8B;
1135
case kFormat8H:
1136
return kFormat4H;
1137
case kFormat4S:
1138
return kFormat2S;
1139
default:
1140
VIXL_UNREACHABLE();
1141
return kFormatUndefined;
1142
}
1143
}
1144
1145
1146
VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits) {
1147
switch (lane_size_in_bits) {
1148
case 8:
1149
return kFormatB;
1150
case 16:
1151
return kFormatH;
1152
case 32:
1153
return kFormatS;
1154
case 64:
1155
return kFormatD;
1156
default:
1157
VIXL_UNREACHABLE();
1158
return kFormatUndefined;
1159
}
1160
}
1161
1162
1163
bool IsSVEFormat(VectorFormat vform) {
1164
switch (vform) {
1165
case kFormatVnB:
1166
case kFormatVnH:
1167
case kFormatVnS:
1168
case kFormatVnD:
1169
case kFormatVnQ:
1170
case kFormatVnO:
1171
return true;
1172
default:
1173
return false;
1174
}
1175
}
1176
1177
1178
VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes) {
1179
switch (lane_size_in_bytes) {
1180
case 1:
1181
return kFormatVnB;
1182
case 2:
1183
return kFormatVnH;
1184
case 4:
1185
return kFormatVnS;
1186
case 8:
1187
return kFormatVnD;
1188
case 16:
1189
return kFormatVnQ;
1190
default:
1191
VIXL_UNREACHABLE();
1192
return kFormatUndefined;
1193
}
1194
}
1195
1196
1197
VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits) {
1198
switch (lane_size_in_bits) {
1199
case 8:
1200
case 16:
1201
case 32:
1202
case 64:
1203
case 128:
1204
return SVEFormatFromLaneSizeInBytes(lane_size_in_bits / kBitsPerByte);
1205
default:
1206
VIXL_UNREACHABLE();
1207
return kFormatUndefined;
1208
}
1209
}
1210
1211
1212
VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2) {
1213
switch (lane_size_in_bytes_log2) {
1214
case 0:
1215
case 1:
1216
case 2:
1217
case 3:
1218
case 4:
1219
return SVEFormatFromLaneSizeInBytes(1 << lane_size_in_bytes_log2);
1220
default:
1221
VIXL_UNREACHABLE();
1222
return kFormatUndefined;
1223
}
1224
}
1225
1226
1227
VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
1228
return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1229
}
1230
1231
1232
unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
1233
VIXL_ASSERT(vform != kFormatUndefined);
1234
VIXL_ASSERT(!IsSVEFormat(vform));
1235
switch (vform) {
1236
case kFormatB:
1237
return kBRegSize;
1238
case kFormatH:
1239
return kHRegSize;
1240
case kFormatS:
1241
case kFormat2H:
1242
return kSRegSize;
1243
case kFormatD:
1244
case kFormat8B:
1245
case kFormat4H:
1246
case kFormat2S:
1247
case kFormat1D:
1248
return kDRegSize;
1249
case kFormat16B:
1250
case kFormat8H:
1251
case kFormat4S:
1252
case kFormat2D:
1253
case kFormat1Q:
1254
return kQRegSize;
1255
default:
1256
VIXL_UNREACHABLE();
1257
return 0;
1258
}
1259
}
1260
1261
1262
unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
1263
return RegisterSizeInBitsFromFormat(vform) / 8;
1264
}
1265
1266
1267
unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
1268
VIXL_ASSERT(vform != kFormatUndefined);
1269
switch (vform) {
1270
case kFormatB:
1271
case kFormat8B:
1272
case kFormat16B:
1273
case kFormatVnB:
1274
return 8;
1275
case kFormatH:
1276
case kFormat2H:
1277
case kFormat4H:
1278
case kFormat8H:
1279
case kFormatVnH:
1280
return 16;
1281
case kFormatS:
1282
case kFormat2S:
1283
case kFormat4S:
1284
case kFormatVnS:
1285
return 32;
1286
case kFormatD:
1287
case kFormat1D:
1288
case kFormat2D:
1289
case kFormatVnD:
1290
return 64;
1291
case kFormat1Q:
1292
case kFormatVnQ:
1293
return 128;
1294
case kFormatVnO:
1295
return 256;
1296
default:
1297
VIXL_UNREACHABLE();
1298
return 0;
1299
}
1300
}
1301
1302
1303
int LaneSizeInBytesFromFormat(VectorFormat vform) {
1304
return LaneSizeInBitsFromFormat(vform) / 8;
1305
}
1306
1307
1308
int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
1309
VIXL_ASSERT(vform != kFormatUndefined);
1310
switch (vform) {
1311
case kFormatB:
1312
case kFormat8B:
1313
case kFormat16B:
1314
case kFormatVnB:
1315
return 0;
1316
case kFormatH:
1317
case kFormat2H:
1318
case kFormat4H:
1319
case kFormat8H:
1320
case kFormatVnH:
1321
return 1;
1322
case kFormatS:
1323
case kFormat2S:
1324
case kFormat4S:
1325
case kFormatVnS:
1326
return 2;
1327
case kFormatD:
1328
case kFormat1D:
1329
case kFormat2D:
1330
case kFormatVnD:
1331
return 3;
1332
case kFormatVnQ:
1333
return 4;
1334
default:
1335
VIXL_UNREACHABLE();
1336
return 0;
1337
}
1338
}
1339
1340
1341
int LaneCountFromFormat(VectorFormat vform) {
1342
VIXL_ASSERT(vform != kFormatUndefined);
1343
switch (vform) {
1344
case kFormat16B:
1345
return 16;
1346
case kFormat8B:
1347
case kFormat8H:
1348
return 8;
1349
case kFormat4H:
1350
case kFormat4S:
1351
return 4;
1352
case kFormat2H:
1353
case kFormat2S:
1354
case kFormat2D:
1355
return 2;
1356
case kFormat1D:
1357
case kFormat1Q:
1358
case kFormatB:
1359
case kFormatH:
1360
case kFormatS:
1361
case kFormatD:
1362
return 1;
1363
default:
1364
VIXL_UNREACHABLE();
1365
return 0;
1366
}
1367
}
1368
1369
1370
int MaxLaneCountFromFormat(VectorFormat vform) {
1371
VIXL_ASSERT(vform != kFormatUndefined);
1372
switch (vform) {
1373
case kFormatB:
1374
case kFormat8B:
1375
case kFormat16B:
1376
return 16;
1377
case kFormatH:
1378
case kFormat4H:
1379
case kFormat8H:
1380
return 8;
1381
case kFormatS:
1382
case kFormat2S:
1383
case kFormat4S:
1384
return 4;
1385
case kFormatD:
1386
case kFormat1D:
1387
case kFormat2D:
1388
return 2;
1389
default:
1390
VIXL_UNREACHABLE();
1391
return 0;
1392
}
1393
}
1394
1395
1396
// Does 'vform' indicate a vector format or a scalar format?
1397
bool IsVectorFormat(VectorFormat vform) {
1398
VIXL_ASSERT(vform != kFormatUndefined);
1399
switch (vform) {
1400
case kFormatB:
1401
case kFormatH:
1402
case kFormatS:
1403
case kFormatD:
1404
return false;
1405
default:
1406
return true;
1407
}
1408
}
1409
1410
1411
int64_t MaxIntFromFormat(VectorFormat vform) {
1412
int lane_size = LaneSizeInBitsFromFormat(vform);
1413
return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
1414
}
1415
1416
1417
int64_t MinIntFromFormat(VectorFormat vform) {
1418
return -MaxIntFromFormat(vform) - 1;
1419
}
1420
1421
1422
uint64_t MaxUintFromFormat(VectorFormat vform) {
1423
return GetUintMask(LaneSizeInBitsFromFormat(vform));
1424
}
1425
1426
} // namespace aarch64
1427
} // namespace vixl
1428
1429