Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/vixl/src/aarch64/cpu-features-auditor-aarch64.cc
4261 views
1
// Copyright 2018, 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 "cpu-features-auditor-aarch64.h"
28
29
#include "cpu-features.h"
30
#include "globals-vixl.h"
31
#include "utils-vixl.h"
32
33
#include "decoder-aarch64.h"
34
35
namespace vixl {
36
namespace aarch64 {
37
38
39
const CPUFeaturesAuditor::FormToVisitorFnMap*
40
CPUFeaturesAuditor::GetFormToVisitorFnMap() {
41
static const FormToVisitorFnMap form_to_visitor = {
42
DEFAULT_FORM_TO_VISITOR_MAP(CPUFeaturesAuditor),
43
SIM_AUD_VISITOR_MAP(CPUFeaturesAuditor),
44
{"fcmla_asimdelem_c_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
45
{"fcmla_asimdelem_c_s"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
46
{"fmlal2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
47
{"fmlal_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
48
{"fmla_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
49
{"fmla_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
50
{"fmlsl2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
51
{"fmlsl_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
52
{"fmls_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
53
{"fmls_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
54
{"fmulx_asimdelem_rh_h"_h,
55
&CPUFeaturesAuditor::VisitNEONByIndexedElement},
56
{"fmulx_asimdelem_r_sd"_h,
57
&CPUFeaturesAuditor::VisitNEONByIndexedElement},
58
{"fmul_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
59
{"fmul_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
60
{"sdot_asimdelem_d"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
61
{"smlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
62
{"smlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
63
{"smull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
64
{"sqdmlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
65
{"sqdmlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
66
{"sqdmull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
67
{"udot_asimdelem_d"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
68
{"umlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
69
{"umlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
70
{"umull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
71
};
72
return &form_to_visitor;
73
}
74
75
// Every instruction must update last_instruction_, even if only to clear it,
76
// and every instruction must also update seen_ once it has been fully handled.
77
// This scope makes that simple, and allows early returns in the decode logic.
78
class CPUFeaturesAuditor::RecordInstructionFeaturesScope {
79
public:
80
explicit RecordInstructionFeaturesScope(CPUFeaturesAuditor* auditor)
81
: auditor_(auditor) {
82
auditor_->last_instruction_ = CPUFeatures::None();
83
}
84
~RecordInstructionFeaturesScope() {
85
auditor_->seen_.Combine(auditor_->last_instruction_);
86
}
87
88
void Record(const CPUFeatures& features) {
89
auditor_->last_instruction_.Combine(features);
90
}
91
92
void Record(CPUFeatures::Feature feature0,
93
CPUFeatures::Feature feature1 = CPUFeatures::kNone,
94
CPUFeatures::Feature feature2 = CPUFeatures::kNone,
95
CPUFeatures::Feature feature3 = CPUFeatures::kNone) {
96
auditor_->last_instruction_.Combine(feature0, feature1, feature2, feature3);
97
}
98
99
// If exactly one of a or b is known to be available, record it. Otherwise,
100
// record both. This is intended for encodings that can be provided by two
101
// different features.
102
void RecordOneOrBothOf(CPUFeatures::Feature a, CPUFeatures::Feature b) {
103
bool hint_a = auditor_->available_.Has(a);
104
bool hint_b = auditor_->available_.Has(b);
105
if (hint_a && !hint_b) {
106
Record(a);
107
} else if (hint_b && !hint_a) {
108
Record(b);
109
} else {
110
Record(a, b);
111
}
112
}
113
114
private:
115
CPUFeaturesAuditor* auditor_;
116
};
117
118
void CPUFeaturesAuditor::LoadStoreHelper(const Instruction* instr) {
119
RecordInstructionFeaturesScope scope(this);
120
switch (instr->Mask(LoadStoreMask)) {
121
case LDR_b:
122
case LDR_q:
123
case STR_b:
124
case STR_q:
125
scope.Record(CPUFeatures::kNEON);
126
return;
127
case LDR_h:
128
case LDR_s:
129
case LDR_d:
130
case STR_h:
131
case STR_s:
132
case STR_d:
133
scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON);
134
return;
135
default:
136
// No special CPU features.
137
return;
138
}
139
}
140
141
void CPUFeaturesAuditor::LoadStorePairHelper(const Instruction* instr) {
142
RecordInstructionFeaturesScope scope(this);
143
switch (instr->Mask(LoadStorePairMask)) {
144
case LDP_q:
145
case STP_q:
146
scope.Record(CPUFeatures::kNEON);
147
return;
148
case LDP_s:
149
case LDP_d:
150
case STP_s:
151
case STP_d: {
152
scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON);
153
return;
154
}
155
default:
156
// No special CPU features.
157
return;
158
}
159
}
160
161
void CPUFeaturesAuditor::VisitAddSubExtended(const Instruction* instr) {
162
RecordInstructionFeaturesScope scope(this);
163
USE(instr);
164
}
165
166
void CPUFeaturesAuditor::VisitAddSubImmediate(const Instruction* instr) {
167
RecordInstructionFeaturesScope scope(this);
168
USE(instr);
169
}
170
171
void CPUFeaturesAuditor::VisitAddSubShifted(const Instruction* instr) {
172
RecordInstructionFeaturesScope scope(this);
173
USE(instr);
174
}
175
176
void CPUFeaturesAuditor::VisitAddSubWithCarry(const Instruction* instr) {
177
RecordInstructionFeaturesScope scope(this);
178
USE(instr);
179
}
180
181
void CPUFeaturesAuditor::VisitRotateRightIntoFlags(const Instruction* instr) {
182
RecordInstructionFeaturesScope scope(this);
183
switch (instr->Mask(RotateRightIntoFlagsMask)) {
184
case RMIF:
185
scope.Record(CPUFeatures::kFlagM);
186
return;
187
}
188
}
189
190
void CPUFeaturesAuditor::VisitEvaluateIntoFlags(const Instruction* instr) {
191
RecordInstructionFeaturesScope scope(this);
192
switch (instr->Mask(EvaluateIntoFlagsMask)) {
193
case SETF8:
194
case SETF16:
195
scope.Record(CPUFeatures::kFlagM);
196
return;
197
}
198
}
199
200
void CPUFeaturesAuditor::VisitAtomicMemory(const Instruction* instr) {
201
RecordInstructionFeaturesScope scope(this);
202
switch (instr->Mask(AtomicMemoryMask)) {
203
case LDAPRB:
204
case LDAPRH:
205
case LDAPR_w:
206
case LDAPR_x:
207
scope.Record(CPUFeatures::kRCpc);
208
return;
209
default:
210
// Everything else belongs to the Atomics extension.
211
scope.Record(CPUFeatures::kAtomics);
212
return;
213
}
214
}
215
216
void CPUFeaturesAuditor::VisitBitfield(const Instruction* instr) {
217
RecordInstructionFeaturesScope scope(this);
218
USE(instr);
219
}
220
221
void CPUFeaturesAuditor::VisitCompareBranch(const Instruction* instr) {
222
RecordInstructionFeaturesScope scope(this);
223
USE(instr);
224
}
225
226
void CPUFeaturesAuditor::VisitConditionalBranch(const Instruction* instr) {
227
RecordInstructionFeaturesScope scope(this);
228
USE(instr);
229
}
230
231
void CPUFeaturesAuditor::VisitConditionalCompareImmediate(
232
const Instruction* instr) {
233
RecordInstructionFeaturesScope scope(this);
234
USE(instr);
235
}
236
237
void CPUFeaturesAuditor::VisitConditionalCompareRegister(
238
const Instruction* instr) {
239
RecordInstructionFeaturesScope scope(this);
240
USE(instr);
241
}
242
243
void CPUFeaturesAuditor::VisitConditionalSelect(const Instruction* instr) {
244
RecordInstructionFeaturesScope scope(this);
245
USE(instr);
246
}
247
248
void CPUFeaturesAuditor::VisitCrypto2RegSHA(const Instruction* instr) {
249
RecordInstructionFeaturesScope scope(this);
250
USE(instr);
251
}
252
253
void CPUFeaturesAuditor::VisitCrypto3RegSHA(const Instruction* instr) {
254
RecordInstructionFeaturesScope scope(this);
255
USE(instr);
256
}
257
258
void CPUFeaturesAuditor::VisitCryptoAES(const Instruction* instr) {
259
RecordInstructionFeaturesScope scope(this);
260
USE(instr);
261
}
262
263
void CPUFeaturesAuditor::VisitDataProcessing1Source(const Instruction* instr) {
264
RecordInstructionFeaturesScope scope(this);
265
switch (instr->Mask(DataProcessing1SourceMask)) {
266
case PACIA:
267
case PACIB:
268
case PACDA:
269
case PACDB:
270
case AUTIA:
271
case AUTIB:
272
case AUTDA:
273
case AUTDB:
274
case PACIZA:
275
case PACIZB:
276
case PACDZA:
277
case PACDZB:
278
case AUTIZA:
279
case AUTIZB:
280
case AUTDZA:
281
case AUTDZB:
282
case XPACI:
283
case XPACD:
284
scope.Record(CPUFeatures::kPAuth);
285
return;
286
default:
287
// No special CPU features.
288
return;
289
}
290
}
291
292
void CPUFeaturesAuditor::VisitDataProcessing2Source(const Instruction* instr) {
293
RecordInstructionFeaturesScope scope(this);
294
switch (instr->Mask(DataProcessing2SourceMask)) {
295
case CRC32B:
296
case CRC32H:
297
case CRC32W:
298
case CRC32X:
299
case CRC32CB:
300
case CRC32CH:
301
case CRC32CW:
302
case CRC32CX:
303
scope.Record(CPUFeatures::kCRC32);
304
return;
305
case PACGA:
306
scope.Record(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric);
307
return;
308
default:
309
// No special CPU features.
310
return;
311
}
312
}
313
314
void CPUFeaturesAuditor::VisitLoadStoreRCpcUnscaledOffset(
315
const Instruction* instr) {
316
RecordInstructionFeaturesScope scope(this);
317
switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
318
case LDAPURB:
319
case LDAPURSB_w:
320
case LDAPURSB_x:
321
case LDAPURH:
322
case LDAPURSH_w:
323
case LDAPURSH_x:
324
case LDAPUR_w:
325
case LDAPURSW:
326
case LDAPUR_x:
327
328
// These stores don't actually have RCpc semantics but they're included with
329
// the RCpc extensions.
330
case STLURB:
331
case STLURH:
332
case STLUR_w:
333
case STLUR_x:
334
scope.Record(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm);
335
return;
336
}
337
}
338
339
void CPUFeaturesAuditor::VisitLoadStorePAC(const Instruction* instr) {
340
RecordInstructionFeaturesScope scope(this);
341
USE(instr);
342
scope.Record(CPUFeatures::kPAuth);
343
}
344
345
void CPUFeaturesAuditor::VisitDataProcessing3Source(const Instruction* instr) {
346
RecordInstructionFeaturesScope scope(this);
347
USE(instr);
348
}
349
350
void CPUFeaturesAuditor::VisitException(const Instruction* instr) {
351
RecordInstructionFeaturesScope scope(this);
352
USE(instr);
353
}
354
355
void CPUFeaturesAuditor::VisitExtract(const Instruction* instr) {
356
RecordInstructionFeaturesScope scope(this);
357
USE(instr);
358
}
359
360
void CPUFeaturesAuditor::VisitFPCompare(const Instruction* instr) {
361
RecordInstructionFeaturesScope scope(this);
362
// All of these instructions require FP.
363
scope.Record(CPUFeatures::kFP);
364
switch (instr->Mask(FPCompareMask)) {
365
case FCMP_h:
366
case FCMP_h_zero:
367
case FCMPE_h:
368
case FCMPE_h_zero:
369
scope.Record(CPUFeatures::kFPHalf);
370
return;
371
default:
372
// No special CPU features.
373
return;
374
}
375
}
376
377
void CPUFeaturesAuditor::VisitFPConditionalCompare(const Instruction* instr) {
378
RecordInstructionFeaturesScope scope(this);
379
// All of these instructions require FP.
380
scope.Record(CPUFeatures::kFP);
381
switch (instr->Mask(FPConditionalCompareMask)) {
382
case FCCMP_h:
383
case FCCMPE_h:
384
scope.Record(CPUFeatures::kFPHalf);
385
return;
386
default:
387
// No special CPU features.
388
return;
389
}
390
}
391
392
void CPUFeaturesAuditor::VisitFPConditionalSelect(const Instruction* instr) {
393
RecordInstructionFeaturesScope scope(this);
394
// All of these instructions require FP.
395
scope.Record(CPUFeatures::kFP);
396
if (instr->Mask(FPConditionalSelectMask) == FCSEL_h) {
397
scope.Record(CPUFeatures::kFPHalf);
398
}
399
}
400
401
void CPUFeaturesAuditor::VisitFPDataProcessing1Source(
402
const Instruction* instr) {
403
RecordInstructionFeaturesScope scope(this);
404
// All of these instructions require FP.
405
scope.Record(CPUFeatures::kFP);
406
switch (instr->Mask(FPDataProcessing1SourceMask)) {
407
case FMOV_h:
408
case FABS_h:
409
case FNEG_h:
410
case FSQRT_h:
411
case FRINTN_h:
412
case FRINTP_h:
413
case FRINTM_h:
414
case FRINTZ_h:
415
case FRINTA_h:
416
case FRINTX_h:
417
case FRINTI_h:
418
scope.Record(CPUFeatures::kFPHalf);
419
return;
420
case FRINT32X_s:
421
case FRINT32X_d:
422
case FRINT32Z_s:
423
case FRINT32Z_d:
424
case FRINT64X_s:
425
case FRINT64X_d:
426
case FRINT64Z_s:
427
case FRINT64Z_d:
428
scope.Record(CPUFeatures::kFrintToFixedSizedInt);
429
return;
430
default:
431
// No special CPU features.
432
// This category includes some half-precision FCVT instructions that do
433
// not require FPHalf.
434
return;
435
}
436
}
437
438
void CPUFeaturesAuditor::VisitFPDataProcessing2Source(
439
const Instruction* instr) {
440
RecordInstructionFeaturesScope scope(this);
441
// All of these instructions require FP.
442
scope.Record(CPUFeatures::kFP);
443
switch (instr->Mask(FPDataProcessing2SourceMask)) {
444
case FMUL_h:
445
case FDIV_h:
446
case FADD_h:
447
case FSUB_h:
448
case FMAX_h:
449
case FMIN_h:
450
case FMAXNM_h:
451
case FMINNM_h:
452
case FNMUL_h:
453
scope.Record(CPUFeatures::kFPHalf);
454
return;
455
default:
456
// No special CPU features.
457
return;
458
}
459
}
460
461
void CPUFeaturesAuditor::VisitFPDataProcessing3Source(
462
const Instruction* instr) {
463
RecordInstructionFeaturesScope scope(this);
464
// All of these instructions require FP.
465
scope.Record(CPUFeatures::kFP);
466
switch (instr->Mask(FPDataProcessing3SourceMask)) {
467
case FMADD_h:
468
case FMSUB_h:
469
case FNMADD_h:
470
case FNMSUB_h:
471
scope.Record(CPUFeatures::kFPHalf);
472
return;
473
default:
474
// No special CPU features.
475
return;
476
}
477
}
478
479
void CPUFeaturesAuditor::VisitFPFixedPointConvert(const Instruction* instr) {
480
RecordInstructionFeaturesScope scope(this);
481
// All of these instructions require FP.
482
scope.Record(CPUFeatures::kFP);
483
switch (instr->Mask(FPFixedPointConvertMask)) {
484
case FCVTZS_wh_fixed:
485
case FCVTZS_xh_fixed:
486
case FCVTZU_wh_fixed:
487
case FCVTZU_xh_fixed:
488
case SCVTF_hw_fixed:
489
case SCVTF_hx_fixed:
490
case UCVTF_hw_fixed:
491
case UCVTF_hx_fixed:
492
scope.Record(CPUFeatures::kFPHalf);
493
return;
494
default:
495
// No special CPU features.
496
return;
497
}
498
}
499
500
void CPUFeaturesAuditor::VisitFPImmediate(const Instruction* instr) {
501
RecordInstructionFeaturesScope scope(this);
502
// All of these instructions require FP.
503
scope.Record(CPUFeatures::kFP);
504
if (instr->Mask(FPImmediateMask) == FMOV_h_imm) {
505
scope.Record(CPUFeatures::kFPHalf);
506
}
507
}
508
509
void CPUFeaturesAuditor::VisitFPIntegerConvert(const Instruction* instr) {
510
RecordInstructionFeaturesScope scope(this);
511
switch (instr->Mask(FPIntegerConvertMask)) {
512
case FCVTAS_wh:
513
case FCVTAS_xh:
514
case FCVTAU_wh:
515
case FCVTAU_xh:
516
case FCVTMS_wh:
517
case FCVTMS_xh:
518
case FCVTMU_wh:
519
case FCVTMU_xh:
520
case FCVTNS_wh:
521
case FCVTNS_xh:
522
case FCVTNU_wh:
523
case FCVTNU_xh:
524
case FCVTPS_wh:
525
case FCVTPS_xh:
526
case FCVTPU_wh:
527
case FCVTPU_xh:
528
case FCVTZS_wh:
529
case FCVTZS_xh:
530
case FCVTZU_wh:
531
case FCVTZU_xh:
532
case FMOV_hw:
533
case FMOV_hx:
534
case FMOV_wh:
535
case FMOV_xh:
536
case SCVTF_hw:
537
case SCVTF_hx:
538
case UCVTF_hw:
539
case UCVTF_hx:
540
scope.Record(CPUFeatures::kFP);
541
scope.Record(CPUFeatures::kFPHalf);
542
return;
543
case FMOV_dx:
544
scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON);
545
return;
546
case FMOV_d1_x:
547
case FMOV_x_d1:
548
scope.Record(CPUFeatures::kFP);
549
scope.Record(CPUFeatures::kNEON);
550
return;
551
case FJCVTZS:
552
scope.Record(CPUFeatures::kFP);
553
scope.Record(CPUFeatures::kJSCVT);
554
return;
555
default:
556
scope.Record(CPUFeatures::kFP);
557
return;
558
}
559
}
560
561
void CPUFeaturesAuditor::VisitLoadLiteral(const Instruction* instr) {
562
RecordInstructionFeaturesScope scope(this);
563
switch (instr->Mask(LoadLiteralMask)) {
564
case LDR_s_lit:
565
case LDR_d_lit:
566
scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON);
567
return;
568
case LDR_q_lit:
569
scope.Record(CPUFeatures::kNEON);
570
return;
571
default:
572
// No special CPU features.
573
return;
574
}
575
}
576
577
void CPUFeaturesAuditor::VisitLoadStoreExclusive(const Instruction* instr) {
578
RecordInstructionFeaturesScope scope(this);
579
switch (instr->Mask(LoadStoreExclusiveMask)) {
580
case CAS_w:
581
case CASA_w:
582
case CASL_w:
583
case CASAL_w:
584
case CAS_x:
585
case CASA_x:
586
case CASL_x:
587
case CASAL_x:
588
case CASB:
589
case CASAB:
590
case CASLB:
591
case CASALB:
592
case CASH:
593
case CASAH:
594
case CASLH:
595
case CASALH:
596
case CASP_w:
597
case CASPA_w:
598
case CASPL_w:
599
case CASPAL_w:
600
case CASP_x:
601
case CASPA_x:
602
case CASPL_x:
603
case CASPAL_x:
604
scope.Record(CPUFeatures::kAtomics);
605
return;
606
case STLLRB:
607
case LDLARB:
608
case STLLRH:
609
case LDLARH:
610
case STLLR_w:
611
case LDLAR_w:
612
case STLLR_x:
613
case LDLAR_x:
614
scope.Record(CPUFeatures::kLORegions);
615
return;
616
default:
617
// No special CPU features.
618
return;
619
}
620
}
621
622
void CPUFeaturesAuditor::VisitLoadStorePairNonTemporal(
623
const Instruction* instr) {
624
LoadStorePairHelper(instr);
625
}
626
627
void CPUFeaturesAuditor::VisitLoadStorePairOffset(const Instruction* instr) {
628
LoadStorePairHelper(instr);
629
}
630
631
void CPUFeaturesAuditor::VisitLoadStorePairPostIndex(const Instruction* instr) {
632
LoadStorePairHelper(instr);
633
}
634
635
void CPUFeaturesAuditor::VisitLoadStorePairPreIndex(const Instruction* instr) {
636
LoadStorePairHelper(instr);
637
}
638
639
void CPUFeaturesAuditor::VisitLoadStorePostIndex(const Instruction* instr) {
640
LoadStoreHelper(instr);
641
}
642
643
void CPUFeaturesAuditor::VisitLoadStorePreIndex(const Instruction* instr) {
644
LoadStoreHelper(instr);
645
}
646
647
void CPUFeaturesAuditor::VisitLoadStoreRegisterOffset(
648
const Instruction* instr) {
649
LoadStoreHelper(instr);
650
}
651
652
void CPUFeaturesAuditor::VisitLoadStoreUnscaledOffset(
653
const Instruction* instr) {
654
LoadStoreHelper(instr);
655
}
656
657
void CPUFeaturesAuditor::VisitLoadStoreUnsignedOffset(
658
const Instruction* instr) {
659
LoadStoreHelper(instr);
660
}
661
662
void CPUFeaturesAuditor::VisitLogicalImmediate(const Instruction* instr) {
663
RecordInstructionFeaturesScope scope(this);
664
USE(instr);
665
}
666
667
void CPUFeaturesAuditor::VisitLogicalShifted(const Instruction* instr) {
668
RecordInstructionFeaturesScope scope(this);
669
USE(instr);
670
}
671
672
void CPUFeaturesAuditor::VisitMoveWideImmediate(const Instruction* instr) {
673
RecordInstructionFeaturesScope scope(this);
674
USE(instr);
675
}
676
677
void CPUFeaturesAuditor::VisitNEON2RegMisc(const Instruction* instr) {
678
RecordInstructionFeaturesScope scope(this);
679
// All of these instructions require NEON.
680
scope.Record(CPUFeatures::kNEON);
681
switch (instr->Mask(NEON2RegMiscFPMask)) {
682
case NEON_FABS:
683
case NEON_FNEG:
684
case NEON_FSQRT:
685
case NEON_FCVTL:
686
case NEON_FCVTN:
687
case NEON_FCVTXN:
688
case NEON_FRINTI:
689
case NEON_FRINTX:
690
case NEON_FRINTA:
691
case NEON_FRINTM:
692
case NEON_FRINTN:
693
case NEON_FRINTP:
694
case NEON_FRINTZ:
695
case NEON_FCVTNS:
696
case NEON_FCVTNU:
697
case NEON_FCVTPS:
698
case NEON_FCVTPU:
699
case NEON_FCVTMS:
700
case NEON_FCVTMU:
701
case NEON_FCVTZS:
702
case NEON_FCVTZU:
703
case NEON_FCVTAS:
704
case NEON_FCVTAU:
705
case NEON_SCVTF:
706
case NEON_UCVTF:
707
case NEON_FRSQRTE:
708
case NEON_FRECPE:
709
case NEON_FCMGT_zero:
710
case NEON_FCMGE_zero:
711
case NEON_FCMEQ_zero:
712
case NEON_FCMLE_zero:
713
case NEON_FCMLT_zero:
714
scope.Record(CPUFeatures::kFP);
715
return;
716
case NEON_FRINT32X:
717
case NEON_FRINT32Z:
718
case NEON_FRINT64X:
719
case NEON_FRINT64Z:
720
scope.Record(CPUFeatures::kFP, CPUFeatures::kFrintToFixedSizedInt);
721
return;
722
default:
723
// No additional features.
724
return;
725
}
726
}
727
728
void CPUFeaturesAuditor::VisitNEON2RegMiscFP16(const Instruction* instr) {
729
RecordInstructionFeaturesScope scope(this);
730
// All of these instructions require NEONHalf.
731
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf);
732
USE(instr);
733
}
734
735
void CPUFeaturesAuditor::VisitNEON3Different(const Instruction* instr) {
736
RecordInstructionFeaturesScope scope(this);
737
// All of these instructions require NEON.
738
scope.Record(CPUFeatures::kNEON);
739
if (form_hash_ == "pmull_asimddiff_l"_h) {
740
if (instr->GetNEONSize() == 3) {
741
// Source is 1D or 2D, destination is 1Q.
742
scope.Record(CPUFeatures::kPmull1Q);
743
}
744
}
745
USE(instr);
746
}
747
748
void CPUFeaturesAuditor::VisitNEON3Same(const Instruction* instr) {
749
RecordInstructionFeaturesScope scope(this);
750
// All of these instructions require NEON.
751
scope.Record(CPUFeatures::kNEON);
752
if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
753
scope.Record(CPUFeatures::kFP);
754
}
755
switch (instr->Mask(NEON3SameFHMMask)) {
756
case NEON_FMLAL:
757
case NEON_FMLAL2:
758
case NEON_FMLSL:
759
case NEON_FMLSL2:
760
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf, CPUFeatures::kFHM);
761
return;
762
default:
763
// No additional features.
764
return;
765
}
766
}
767
768
void CPUFeaturesAuditor::VisitNEON3SameExtra(const Instruction* instr) {
769
RecordInstructionFeaturesScope scope(this);
770
// All of these instructions require NEON.
771
scope.Record(CPUFeatures::kNEON);
772
if ((instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) ||
773
(instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD)) {
774
scope.Record(CPUFeatures::kFP, CPUFeatures::kFcma);
775
if (instr->GetNEONSize() == 1) scope.Record(CPUFeatures::kNEONHalf);
776
} else {
777
switch (instr->Mask(NEON3SameExtraMask)) {
778
case NEON_SDOT:
779
case NEON_UDOT:
780
scope.Record(CPUFeatures::kDotProduct);
781
return;
782
case NEON_SQRDMLAH:
783
case NEON_SQRDMLSH:
784
scope.Record(CPUFeatures::kRDM);
785
return;
786
default:
787
// No additional features.
788
return;
789
}
790
}
791
}
792
793
void CPUFeaturesAuditor::VisitNEON3SameFP16(const Instruction* instr) {
794
RecordInstructionFeaturesScope scope(this);
795
// All of these instructions require NEON FP16 support.
796
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf);
797
USE(instr);
798
}
799
800
void CPUFeaturesAuditor::VisitNEONAcrossLanes(const Instruction* instr) {
801
RecordInstructionFeaturesScope scope(this);
802
// All of these instructions require NEON.
803
scope.Record(CPUFeatures::kNEON);
804
if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
805
// FMAXV_H, FMINV_H, FMAXNMV_H, FMINNMV_H
806
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf);
807
} else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
808
// FMAXV, FMINV, FMAXNMV, FMINNMV
809
scope.Record(CPUFeatures::kFP);
810
}
811
}
812
813
void CPUFeaturesAuditor::VisitNEONByIndexedElement(const Instruction* instr) {
814
RecordInstructionFeaturesScope scope(this);
815
// All of these instructions require NEON.
816
scope.Record(CPUFeatures::kNEON);
817
switch (instr->Mask(NEONByIndexedElementMask)) {
818
case NEON_SDOT_byelement:
819
case NEON_UDOT_byelement:
820
scope.Record(CPUFeatures::kDotProduct);
821
return;
822
case NEON_SQRDMLAH_byelement:
823
case NEON_SQRDMLSH_byelement:
824
scope.Record(CPUFeatures::kRDM);
825
return;
826
default:
827
// Fall through to check other instructions.
828
break;
829
}
830
switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
831
case NEON_FMLAL_H_byelement:
832
case NEON_FMLAL2_H_byelement:
833
case NEON_FMLSL_H_byelement:
834
case NEON_FMLSL2_H_byelement:
835
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf, CPUFeatures::kFHM);
836
return;
837
default:
838
// Fall through to check other instructions.
839
break;
840
}
841
switch (instr->Mask(NEONByIndexedElementFPMask)) {
842
case NEON_FMLA_H_byelement:
843
case NEON_FMLS_H_byelement:
844
case NEON_FMUL_H_byelement:
845
case NEON_FMULX_H_byelement:
846
scope.Record(CPUFeatures::kNEONHalf);
847
VIXL_FALLTHROUGH();
848
case NEON_FMLA_byelement:
849
case NEON_FMLS_byelement:
850
case NEON_FMUL_byelement:
851
case NEON_FMULX_byelement:
852
scope.Record(CPUFeatures::kFP);
853
return;
854
default:
855
switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
856
case NEON_FCMLA_byelement:
857
scope.Record(CPUFeatures::kFP, CPUFeatures::kFcma);
858
if (instr->GetNEONSize() == 1) scope.Record(CPUFeatures::kNEONHalf);
859
return;
860
}
861
// No additional features.
862
return;
863
}
864
}
865
866
void CPUFeaturesAuditor::VisitNEONCopy(const Instruction* instr) {
867
RecordInstructionFeaturesScope scope(this);
868
// All of these instructions require NEON.
869
scope.Record(CPUFeatures::kNEON);
870
USE(instr);
871
}
872
873
void CPUFeaturesAuditor::VisitNEONExtract(const Instruction* instr) {
874
RecordInstructionFeaturesScope scope(this);
875
// All of these instructions require NEON.
876
scope.Record(CPUFeatures::kNEON);
877
USE(instr);
878
}
879
880
void CPUFeaturesAuditor::VisitNEONLoadStoreMultiStruct(
881
const Instruction* instr) {
882
RecordInstructionFeaturesScope scope(this);
883
// All of these instructions require NEON.
884
scope.Record(CPUFeatures::kNEON);
885
USE(instr);
886
}
887
888
void CPUFeaturesAuditor::VisitNEONLoadStoreMultiStructPostIndex(
889
const Instruction* instr) {
890
RecordInstructionFeaturesScope scope(this);
891
// All of these instructions require NEON.
892
scope.Record(CPUFeatures::kNEON);
893
USE(instr);
894
}
895
896
void CPUFeaturesAuditor::VisitNEONLoadStoreSingleStruct(
897
const Instruction* instr) {
898
RecordInstructionFeaturesScope scope(this);
899
// All of these instructions require NEON.
900
scope.Record(CPUFeatures::kNEON);
901
USE(instr);
902
}
903
904
void CPUFeaturesAuditor::VisitNEONLoadStoreSingleStructPostIndex(
905
const Instruction* instr) {
906
RecordInstructionFeaturesScope scope(this);
907
// All of these instructions require NEON.
908
scope.Record(CPUFeatures::kNEON);
909
USE(instr);
910
}
911
912
void CPUFeaturesAuditor::VisitNEONModifiedImmediate(const Instruction* instr) {
913
RecordInstructionFeaturesScope scope(this);
914
// All of these instructions require NEON.
915
scope.Record(CPUFeatures::kNEON);
916
if (instr->GetNEONCmode() == 0xf) {
917
// FMOV (vector, immediate), double-, single- or half-precision.
918
scope.Record(CPUFeatures::kFP);
919
if (instr->ExtractBit(11)) scope.Record(CPUFeatures::kNEONHalf);
920
}
921
}
922
923
void CPUFeaturesAuditor::VisitNEONPerm(const Instruction* instr) {
924
RecordInstructionFeaturesScope scope(this);
925
// All of these instructions require NEON.
926
scope.Record(CPUFeatures::kNEON);
927
USE(instr);
928
}
929
930
void CPUFeaturesAuditor::VisitNEONScalar2RegMisc(const Instruction* instr) {
931
RecordInstructionFeaturesScope scope(this);
932
// All of these instructions require NEON.
933
scope.Record(CPUFeatures::kNEON);
934
switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
935
case NEON_FRECPE_scalar:
936
case NEON_FRECPX_scalar:
937
case NEON_FRSQRTE_scalar:
938
case NEON_FCMGT_zero_scalar:
939
case NEON_FCMGE_zero_scalar:
940
case NEON_FCMEQ_zero_scalar:
941
case NEON_FCMLE_zero_scalar:
942
case NEON_FCMLT_zero_scalar:
943
case NEON_SCVTF_scalar:
944
case NEON_UCVTF_scalar:
945
case NEON_FCVTNS_scalar:
946
case NEON_FCVTNU_scalar:
947
case NEON_FCVTPS_scalar:
948
case NEON_FCVTPU_scalar:
949
case NEON_FCVTMS_scalar:
950
case NEON_FCVTMU_scalar:
951
case NEON_FCVTZS_scalar:
952
case NEON_FCVTZU_scalar:
953
case NEON_FCVTAS_scalar:
954
case NEON_FCVTAU_scalar:
955
case NEON_FCVTXN_scalar:
956
scope.Record(CPUFeatures::kFP);
957
return;
958
default:
959
// No additional features.
960
return;
961
}
962
}
963
964
void CPUFeaturesAuditor::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
965
RecordInstructionFeaturesScope scope(this);
966
// All of these instructions require NEONHalf.
967
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf);
968
USE(instr);
969
}
970
971
void CPUFeaturesAuditor::VisitNEONScalar3Diff(const Instruction* instr) {
972
RecordInstructionFeaturesScope scope(this);
973
// All of these instructions require NEON.
974
scope.Record(CPUFeatures::kNEON);
975
USE(instr);
976
}
977
978
void CPUFeaturesAuditor::VisitNEONScalar3Same(const Instruction* instr) {
979
RecordInstructionFeaturesScope scope(this);
980
// All of these instructions require NEON.
981
scope.Record(CPUFeatures::kNEON);
982
if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
983
scope.Record(CPUFeatures::kFP);
984
}
985
}
986
987
void CPUFeaturesAuditor::VisitNEONScalar3SameExtra(const Instruction* instr) {
988
RecordInstructionFeaturesScope scope(this);
989
// All of these instructions require NEON and RDM.
990
scope.Record(CPUFeatures::kNEON, CPUFeatures::kRDM);
991
USE(instr);
992
}
993
994
void CPUFeaturesAuditor::VisitNEONScalar3SameFP16(const Instruction* instr) {
995
RecordInstructionFeaturesScope scope(this);
996
// All of these instructions require NEONHalf.
997
scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf);
998
USE(instr);
999
}
1000
1001
void CPUFeaturesAuditor::VisitNEONScalarByIndexedElement(
1002
const Instruction* instr) {
1003
RecordInstructionFeaturesScope scope(this);
1004
// All of these instructions require NEON.
1005
scope.Record(CPUFeatures::kNEON);
1006
switch (instr->Mask(NEONScalarByIndexedElementMask)) {
1007
case NEON_SQRDMLAH_byelement_scalar:
1008
case NEON_SQRDMLSH_byelement_scalar:
1009
scope.Record(CPUFeatures::kRDM);
1010
return;
1011
default:
1012
switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
1013
case NEON_FMLA_H_byelement_scalar:
1014
case NEON_FMLS_H_byelement_scalar:
1015
case NEON_FMUL_H_byelement_scalar:
1016
case NEON_FMULX_H_byelement_scalar:
1017
scope.Record(CPUFeatures::kNEONHalf);
1018
VIXL_FALLTHROUGH();
1019
case NEON_FMLA_byelement_scalar:
1020
case NEON_FMLS_byelement_scalar:
1021
case NEON_FMUL_byelement_scalar:
1022
case NEON_FMULX_byelement_scalar:
1023
scope.Record(CPUFeatures::kFP);
1024
return;
1025
}
1026
// No additional features.
1027
return;
1028
}
1029
}
1030
1031
void CPUFeaturesAuditor::VisitNEONScalarCopy(const Instruction* instr) {
1032
RecordInstructionFeaturesScope scope(this);
1033
// All of these instructions require NEON.
1034
scope.Record(CPUFeatures::kNEON);
1035
USE(instr);
1036
}
1037
1038
void CPUFeaturesAuditor::VisitNEONScalarPairwise(const Instruction* instr) {
1039
RecordInstructionFeaturesScope scope(this);
1040
// All of these instructions require NEON.
1041
scope.Record(CPUFeatures::kNEON);
1042
switch (instr->Mask(NEONScalarPairwiseMask)) {
1043
case NEON_FMAXNMP_h_scalar:
1044
case NEON_FADDP_h_scalar:
1045
case NEON_FMAXP_h_scalar:
1046
case NEON_FMINNMP_h_scalar:
1047
case NEON_FMINP_h_scalar:
1048
scope.Record(CPUFeatures::kNEONHalf);
1049
VIXL_FALLTHROUGH();
1050
case NEON_FADDP_scalar:
1051
case NEON_FMAXP_scalar:
1052
case NEON_FMAXNMP_scalar:
1053
case NEON_FMINP_scalar:
1054
case NEON_FMINNMP_scalar:
1055
scope.Record(CPUFeatures::kFP);
1056
return;
1057
default:
1058
// No additional features.
1059
return;
1060
}
1061
}
1062
1063
void CPUFeaturesAuditor::VisitNEONScalarShiftImmediate(
1064
const Instruction* instr) {
1065
RecordInstructionFeaturesScope scope(this);
1066
// All of these instructions require NEON.
1067
scope.Record(CPUFeatures::kNEON);
1068
switch (instr->Mask(NEONScalarShiftImmediateMask)) {
1069
case NEON_FCVTZS_imm_scalar:
1070
case NEON_FCVTZU_imm_scalar:
1071
case NEON_SCVTF_imm_scalar:
1072
case NEON_UCVTF_imm_scalar:
1073
scope.Record(CPUFeatures::kFP);
1074
// If immh is 0b001x then the data type is FP16, and requires kNEONHalf.
1075
if ((instr->GetImmNEONImmh() & 0xe) == 0x2) {
1076
scope.Record(CPUFeatures::kNEONHalf);
1077
}
1078
return;
1079
default:
1080
// No additional features.
1081
return;
1082
}
1083
}
1084
1085
void CPUFeaturesAuditor::VisitNEONShiftImmediate(const Instruction* instr) {
1086
RecordInstructionFeaturesScope scope(this);
1087
// All of these instructions require NEON.
1088
scope.Record(CPUFeatures::kNEON);
1089
switch (instr->Mask(NEONShiftImmediateMask)) {
1090
case NEON_SCVTF_imm:
1091
case NEON_UCVTF_imm:
1092
case NEON_FCVTZS_imm:
1093
case NEON_FCVTZU_imm:
1094
scope.Record(CPUFeatures::kFP);
1095
// If immh is 0b001x then the data type is FP16, and requires kNEONHalf.
1096
if ((instr->GetImmNEONImmh() & 0xe) == 0x2) {
1097
scope.Record(CPUFeatures::kNEONHalf);
1098
}
1099
return;
1100
default:
1101
// No additional features.
1102
return;
1103
}
1104
}
1105
1106
void CPUFeaturesAuditor::VisitNEONTable(const Instruction* instr) {
1107
RecordInstructionFeaturesScope scope(this);
1108
// All of these instructions require NEON.
1109
scope.Record(CPUFeatures::kNEON);
1110
USE(instr);
1111
}
1112
1113
void CPUFeaturesAuditor::VisitPCRelAddressing(const Instruction* instr) {
1114
RecordInstructionFeaturesScope scope(this);
1115
USE(instr);
1116
}
1117
1118
// Most SVE visitors require only SVE.
1119
#define VIXL_SIMPLE_SVE_VISITOR_LIST(V) \
1120
V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \
1121
V(SVE32BitGatherLoad_VectorPlusImm) \
1122
V(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets) \
1123
V(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets) \
1124
V(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets) \
1125
V(SVE32BitGatherPrefetch_VectorPlusImm) \
1126
V(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets) \
1127
V(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets) \
1128
V(SVE32BitScatterStore_VectorPlusImm) \
1129
V(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets) \
1130
V(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsets) \
1131
V(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets) \
1132
V(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets) \
1133
V(SVE64BitGatherLoad_VectorPlusImm) \
1134
V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \
1135
V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \
1136
V(SVE64BitGatherPrefetch_VectorPlusImm) \
1137
V(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets) \
1138
V(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets) \
1139
V(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets) \
1140
V(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets) \
1141
V(SVE64BitScatterStore_VectorPlusImm) \
1142
V(SVEAddressGeneration) \
1143
V(SVEBitwiseLogicalUnpredicated) \
1144
V(SVEBitwiseShiftUnpredicated) \
1145
V(SVEFFRInitialise) \
1146
V(SVEFFRWriteFromPredicate) \
1147
V(SVEFPAccumulatingReduction) \
1148
V(SVEFPArithmeticUnpredicated) \
1149
V(SVEFPCompareVectors) \
1150
V(SVEFPCompareWithZero) \
1151
V(SVEFPComplexAddition) \
1152
V(SVEFPComplexMulAdd) \
1153
V(SVEFPComplexMulAddIndex) \
1154
V(SVEFPFastReduction) \
1155
V(SVEFPMulIndex) \
1156
V(SVEFPMulAdd) \
1157
V(SVEFPMulAddIndex) \
1158
V(SVEFPUnaryOpUnpredicated) \
1159
V(SVEIncDecByPredicateCount) \
1160
V(SVEIndexGeneration) \
1161
V(SVEIntArithmeticUnpredicated) \
1162
V(SVEIntCompareSignedImm) \
1163
V(SVEIntCompareUnsignedImm) \
1164
V(SVEIntCompareVectors) \
1165
V(SVEIntMulAddPredicated) \
1166
V(SVEIntMulAddUnpredicated) \
1167
V(SVEIntReduction) \
1168
V(SVEIntUnaryArithmeticPredicated) \
1169
V(SVEMovprfx) \
1170
V(SVEMulIndex) \
1171
V(SVEPermuteVectorExtract) \
1172
V(SVEPermuteVectorInterleaving) \
1173
V(SVEPredicateCount) \
1174
V(SVEPredicateLogical) \
1175
V(SVEPropagateBreak) \
1176
V(SVEStackFrameAdjustment) \
1177
V(SVEStackFrameSize) \
1178
V(SVEVectorSelect) \
1179
V(SVEBitwiseLogical_Predicated) \
1180
V(SVEBitwiseLogicalWithImm_Unpredicated) \
1181
V(SVEBitwiseShiftByImm_Predicated) \
1182
V(SVEBitwiseShiftByVector_Predicated) \
1183
V(SVEBitwiseShiftByWideElements_Predicated) \
1184
V(SVEBroadcastBitmaskImm) \
1185
V(SVEBroadcastFPImm_Unpredicated) \
1186
V(SVEBroadcastGeneralRegister) \
1187
V(SVEBroadcastIndexElement) \
1188
V(SVEBroadcastIntImm_Unpredicated) \
1189
V(SVECompressActiveElements) \
1190
V(SVEConditionallyBroadcastElementToVector) \
1191
V(SVEConditionallyExtractElementToSIMDFPScalar) \
1192
V(SVEConditionallyExtractElementToGeneralRegister) \
1193
V(SVEConditionallyTerminateScalars) \
1194
V(SVEConstructivePrefix_Unpredicated) \
1195
V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \
1196
V(SVEContiguousLoad_ScalarPlusImm) \
1197
V(SVEContiguousLoad_ScalarPlusScalar) \
1198
V(SVEContiguousNonFaultLoad_ScalarPlusImm) \
1199
V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \
1200
V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \
1201
V(SVEContiguousNonTemporalStore_ScalarPlusImm) \
1202
V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \
1203
V(SVEContiguousPrefetch_ScalarPlusImm) \
1204
V(SVEContiguousPrefetch_ScalarPlusScalar) \
1205
V(SVEContiguousStore_ScalarPlusImm) \
1206
V(SVEContiguousStore_ScalarPlusScalar) \
1207
V(SVECopySIMDFPScalarRegisterToVector_Predicated) \
1208
V(SVECopyFPImm_Predicated) \
1209
V(SVECopyGeneralRegisterToVector_Predicated) \
1210
V(SVECopyIntImm_Predicated) \
1211
V(SVEElementCount) \
1212
V(SVEExtractElementToSIMDFPScalarRegister) \
1213
V(SVEExtractElementToGeneralRegister) \
1214
V(SVEFPArithmetic_Predicated) \
1215
V(SVEFPArithmeticWithImm_Predicated) \
1216
V(SVEFPConvertPrecision) \
1217
V(SVEFPConvertToInt) \
1218
V(SVEFPExponentialAccelerator) \
1219
V(SVEFPRoundToIntegralValue) \
1220
V(SVEFPTrigMulAddCoefficient) \
1221
V(SVEFPTrigSelectCoefficient) \
1222
V(SVEFPUnaryOp) \
1223
V(SVEIncDecRegisterByElementCount) \
1224
V(SVEIncDecVectorByElementCount) \
1225
V(SVEInsertSIMDFPScalarRegister) \
1226
V(SVEInsertGeneralRegister) \
1227
V(SVEIntAddSubtractImm_Unpredicated) \
1228
V(SVEIntAddSubtractVectors_Predicated) \
1229
V(SVEIntCompareScalarCountAndLimit) \
1230
V(SVEIntConvertToFP) \
1231
V(SVEIntDivideVectors_Predicated) \
1232
V(SVEIntMinMaxImm_Unpredicated) \
1233
V(SVEIntMinMaxDifference_Predicated) \
1234
V(SVEIntMulImm_Unpredicated) \
1235
V(SVEIntMulVectors_Predicated) \
1236
V(SVELoadAndBroadcastElement) \
1237
V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \
1238
V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \
1239
V(SVELoadMultipleStructures_ScalarPlusImm) \
1240
V(SVELoadMultipleStructures_ScalarPlusScalar) \
1241
V(SVELoadPredicateRegister) \
1242
V(SVELoadVectorRegister) \
1243
V(SVEPartitionBreakCondition) \
1244
V(SVEPermutePredicateElements) \
1245
V(SVEPredicateFirstActive) \
1246
V(SVEPredicateInitialize) \
1247
V(SVEPredicateNextActive) \
1248
V(SVEPredicateReadFromFFR_Predicated) \
1249
V(SVEPredicateReadFromFFR_Unpredicated) \
1250
V(SVEPredicateTest) \
1251
V(SVEPredicateZero) \
1252
V(SVEPropagateBreakToNextPartition) \
1253
V(SVEReversePredicateElements) \
1254
V(SVEReverseVectorElements) \
1255
V(SVEReverseWithinElements) \
1256
V(SVESaturatingIncDecRegisterByElementCount) \
1257
V(SVESaturatingIncDecVectorByElementCount) \
1258
V(SVEStoreMultipleStructures_ScalarPlusImm) \
1259
V(SVEStoreMultipleStructures_ScalarPlusScalar) \
1260
V(SVEStorePredicateRegister) \
1261
V(SVEStoreVectorRegister) \
1262
V(SVETableLookup) \
1263
V(SVEUnpackPredicateElements) \
1264
V(SVEUnpackVectorElements) \
1265
V(SVEVectorSplice)
1266
1267
#define VIXL_DEFINE_SIMPLE_SVE_VISITOR(NAME) \
1268
void CPUFeaturesAuditor::Visit##NAME(const Instruction* instr) { \
1269
RecordInstructionFeaturesScope scope(this); \
1270
scope.Record(CPUFeatures::kSVE); \
1271
USE(instr); \
1272
}
1273
VIXL_SIMPLE_SVE_VISITOR_LIST(VIXL_DEFINE_SIMPLE_SVE_VISITOR)
1274
#undef VIXL_DEFINE_SIMPLE_SVE_VISITOR
1275
#undef VIXL_SIMPLE_SVE_VISITOR_LIST
1276
1277
void CPUFeaturesAuditor::VisitSystem(const Instruction* instr) {
1278
RecordInstructionFeaturesScope scope(this);
1279
if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
1280
CPUFeatures required;
1281
switch (instr->GetInstructionBits()) {
1282
case PACIA1716:
1283
case PACIB1716:
1284
case AUTIA1716:
1285
case AUTIB1716:
1286
case PACIAZ:
1287
case PACIASP:
1288
case PACIBZ:
1289
case PACIBSP:
1290
case AUTIAZ:
1291
case AUTIASP:
1292
case AUTIBZ:
1293
case AUTIBSP:
1294
case XPACLRI:
1295
required.Combine(CPUFeatures::kPAuth);
1296
break;
1297
default:
1298
switch (instr->GetImmHint()) {
1299
case ESB:
1300
required.Combine(CPUFeatures::kRAS);
1301
break;
1302
case BTI:
1303
case BTI_j:
1304
case BTI_c:
1305
case BTI_jc:
1306
required.Combine(CPUFeatures::kBTI);
1307
break;
1308
default:
1309
break;
1310
}
1311
break;
1312
}
1313
1314
// These are all HINT instructions, and behave as NOPs if the corresponding
1315
// features are not implemented, so we record the corresponding features
1316
// only if they are available.
1317
if (available_.Has(required)) scope.Record(required);
1318
} else if (instr->Mask(SystemSysMask) == SYS) {
1319
switch (instr->GetSysOp()) {
1320
// DC instruction variants.
1321
case CGVAC:
1322
case CGDVAC:
1323
case CGVAP:
1324
case CGDVAP:
1325
case CIGVAC:
1326
case CIGDVAC:
1327
case GVA:
1328
case GZVA:
1329
scope.Record(CPUFeatures::kMTE);
1330
break;
1331
case CVAP:
1332
scope.Record(CPUFeatures::kDCPoP);
1333
break;
1334
case CVADP:
1335
scope.Record(CPUFeatures::kDCCVADP);
1336
break;
1337
case IVAU:
1338
case CVAC:
1339
case CVAU:
1340
case CIVAC:
1341
case ZVA:
1342
// No special CPU features.
1343
break;
1344
}
1345
} else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
1346
switch (instr->Mask(SystemPStateMask)) {
1347
case CFINV:
1348
scope.Record(CPUFeatures::kFlagM);
1349
break;
1350
case AXFLAG:
1351
case XAFLAG:
1352
scope.Record(CPUFeatures::kAXFlag);
1353
break;
1354
}
1355
} else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1356
if (instr->Mask(SystemSysRegMask) == MRS) {
1357
switch (instr->GetImmSystemRegister()) {
1358
case RNDR:
1359
case RNDRRS:
1360
scope.Record(CPUFeatures::kRNG);
1361
break;
1362
}
1363
}
1364
}
1365
}
1366
1367
void CPUFeaturesAuditor::VisitTestBranch(const Instruction* instr) {
1368
RecordInstructionFeaturesScope scope(this);
1369
USE(instr);
1370
}
1371
1372
void CPUFeaturesAuditor::VisitUnallocated(const Instruction* instr) {
1373
RecordInstructionFeaturesScope scope(this);
1374
USE(instr);
1375
}
1376
1377
void CPUFeaturesAuditor::VisitUnconditionalBranch(const Instruction* instr) {
1378
RecordInstructionFeaturesScope scope(this);
1379
USE(instr);
1380
}
1381
1382
void CPUFeaturesAuditor::VisitUnconditionalBranchToRegister(
1383
const Instruction* instr) {
1384
RecordInstructionFeaturesScope scope(this);
1385
switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1386
case BRAAZ:
1387
case BRABZ:
1388
case BLRAAZ:
1389
case BLRABZ:
1390
case RETAA:
1391
case RETAB:
1392
case BRAA:
1393
case BRAB:
1394
case BLRAA:
1395
case BLRAB:
1396
scope.Record(CPUFeatures::kPAuth);
1397
return;
1398
default:
1399
// No additional features.
1400
return;
1401
}
1402
}
1403
1404
void CPUFeaturesAuditor::VisitReserved(const Instruction* instr) {
1405
RecordInstructionFeaturesScope scope(this);
1406
USE(instr);
1407
}
1408
1409
void CPUFeaturesAuditor::VisitUnimplemented(const Instruction* instr) {
1410
RecordInstructionFeaturesScope scope(this);
1411
USE(instr);
1412
}
1413
1414
void CPUFeaturesAuditor::Visit(Metadata* metadata, const Instruction* instr) {
1415
VIXL_ASSERT(metadata->count("form") > 0);
1416
const std::string& form = (*metadata)["form"];
1417
form_hash_ = Hash(form.c_str());
1418
const FormToVisitorFnMap* fv = CPUFeaturesAuditor::GetFormToVisitorFnMap();
1419
FormToVisitorFnMap::const_iterator it = fv->find(form_hash_);
1420
if (it == fv->end()) {
1421
RecordInstructionFeaturesScope scope(this);
1422
std::map<uint32_t, const CPUFeatures> features = {
1423
{"adclb_z_zzz"_h, CPUFeatures::kSVE2},
1424
{"adclt_z_zzz"_h, CPUFeatures::kSVE2},
1425
{"addhnb_z_zz"_h, CPUFeatures::kSVE2},
1426
{"addhnt_z_zz"_h, CPUFeatures::kSVE2},
1427
{"addp_z_p_zz"_h, CPUFeatures::kSVE2},
1428
{"bcax_z_zzz"_h, CPUFeatures::kSVE2},
1429
{"bdep_z_zz"_h,
1430
CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)},
1431
{"bext_z_zz"_h,
1432
CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)},
1433
{"bgrp_z_zz"_h,
1434
CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)},
1435
{"bsl1n_z_zzz"_h, CPUFeatures::kSVE2},
1436
{"bsl2n_z_zzz"_h, CPUFeatures::kSVE2},
1437
{"bsl_z_zzz"_h, CPUFeatures::kSVE2},
1438
{"cadd_z_zz"_h, CPUFeatures::kSVE2},
1439
{"cdot_z_zzz"_h, CPUFeatures::kSVE2},
1440
{"cdot_z_zzzi_d"_h, CPUFeatures::kSVE2},
1441
{"cdot_z_zzzi_s"_h, CPUFeatures::kSVE2},
1442
{"cmla_z_zzz"_h, CPUFeatures::kSVE2},
1443
{"cmla_z_zzzi_h"_h, CPUFeatures::kSVE2},
1444
{"cmla_z_zzzi_s"_h, CPUFeatures::kSVE2},
1445
{"eor3_z_zzz"_h, CPUFeatures::kSVE2},
1446
{"eorbt_z_zz"_h, CPUFeatures::kSVE2},
1447
{"eortb_z_zz"_h, CPUFeatures::kSVE2},
1448
{"ext_z_zi_con"_h, CPUFeatures::kSVE2},
1449
{"faddp_z_p_zz"_h, CPUFeatures::kSVE2},
1450
{"fcvtlt_z_p_z_h2s"_h, CPUFeatures::kSVE2},
1451
{"fcvtlt_z_p_z_s2d"_h, CPUFeatures::kSVE2},
1452
{"fcvtnt_z_p_z_d2s"_h, CPUFeatures::kSVE2},
1453
{"fcvtnt_z_p_z_s2h"_h, CPUFeatures::kSVE2},
1454
{"fcvtx_z_p_z_d2s"_h, CPUFeatures::kSVE2},
1455
{"fcvtxnt_z_p_z_d2s"_h, CPUFeatures::kSVE2},
1456
{"flogb_z_p_z"_h, CPUFeatures::kSVE2},
1457
{"fmaxnmp_z_p_zz"_h, CPUFeatures::kSVE2},
1458
{"fmaxp_z_p_zz"_h, CPUFeatures::kSVE2},
1459
{"fminnmp_z_p_zz"_h, CPUFeatures::kSVE2},
1460
{"fminp_z_p_zz"_h, CPUFeatures::kSVE2},
1461
{"fmlalb_z_zzz"_h, CPUFeatures::kSVE2},
1462
{"fmlalb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1463
{"fmlalt_z_zzz"_h, CPUFeatures::kSVE2},
1464
{"fmlalt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1465
{"fmlslb_z_zzz"_h, CPUFeatures::kSVE2},
1466
{"fmlslb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1467
{"fmlslt_z_zzz"_h, CPUFeatures::kSVE2},
1468
{"fmlslt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1469
{"histcnt_z_p_zz"_h, CPUFeatures::kSVE2},
1470
{"histseg_z_zz"_h, CPUFeatures::kSVE2},
1471
{"ldnt1b_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1472
{"ldnt1b_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1473
{"ldnt1d_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1474
{"ldnt1h_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1475
{"ldnt1h_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1476
{"ldnt1sb_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1477
{"ldnt1sb_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1478
{"ldnt1sh_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1479
{"ldnt1sh_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1480
{"ldnt1sw_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1481
{"ldnt1w_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1482
{"ldnt1w_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1483
{"match_p_p_zz"_h, CPUFeatures::kSVE2},
1484
{"mla_z_zzzi_d"_h, CPUFeatures::kSVE2},
1485
{"mla_z_zzzi_h"_h, CPUFeatures::kSVE2},
1486
{"mla_z_zzzi_s"_h, CPUFeatures::kSVE2},
1487
{"mls_z_zzzi_d"_h, CPUFeatures::kSVE2},
1488
{"mls_z_zzzi_h"_h, CPUFeatures::kSVE2},
1489
{"mls_z_zzzi_s"_h, CPUFeatures::kSVE2},
1490
{"mul_z_zz"_h, CPUFeatures::kSVE2},
1491
{"mul_z_zzi_d"_h, CPUFeatures::kSVE2},
1492
{"mul_z_zzi_h"_h, CPUFeatures::kSVE2},
1493
{"mul_z_zzi_s"_h, CPUFeatures::kSVE2},
1494
{"nbsl_z_zzz"_h, CPUFeatures::kSVE2},
1495
{"nmatch_p_p_zz"_h, CPUFeatures::kSVE2},
1496
{"pmul_z_zz"_h, CPUFeatures::kSVE2},
1497
{"pmullb_z_zz"_h, CPUFeatures::kSVE2},
1498
{"pmullt_z_zz"_h, CPUFeatures::kSVE2},
1499
{"raddhnb_z_zz"_h, CPUFeatures::kSVE2},
1500
{"raddhnt_z_zz"_h, CPUFeatures::kSVE2},
1501
{"rshrnb_z_zi"_h, CPUFeatures::kSVE2},
1502
{"rshrnt_z_zi"_h, CPUFeatures::kSVE2},
1503
{"rsubhnb_z_zz"_h, CPUFeatures::kSVE2},
1504
{"rsubhnt_z_zz"_h, CPUFeatures::kSVE2},
1505
{"saba_z_zzz"_h, CPUFeatures::kSVE2},
1506
{"sabalb_z_zzz"_h, CPUFeatures::kSVE2},
1507
{"sabalt_z_zzz"_h, CPUFeatures::kSVE2},
1508
{"sabdlb_z_zz"_h, CPUFeatures::kSVE2},
1509
{"sabdlt_z_zz"_h, CPUFeatures::kSVE2},
1510
{"sadalp_z_p_z"_h, CPUFeatures::kSVE2},
1511
{"saddlb_z_zz"_h, CPUFeatures::kSVE2},
1512
{"saddlbt_z_zz"_h, CPUFeatures::kSVE2},
1513
{"saddlt_z_zz"_h, CPUFeatures::kSVE2},
1514
{"saddwb_z_zz"_h, CPUFeatures::kSVE2},
1515
{"saddwt_z_zz"_h, CPUFeatures::kSVE2},
1516
{"sbclb_z_zzz"_h, CPUFeatures::kSVE2},
1517
{"sbclt_z_zzz"_h, CPUFeatures::kSVE2},
1518
{"shadd_z_p_zz"_h, CPUFeatures::kSVE2},
1519
{"shrnb_z_zi"_h, CPUFeatures::kSVE2},
1520
{"shrnt_z_zi"_h, CPUFeatures::kSVE2},
1521
{"shsub_z_p_zz"_h, CPUFeatures::kSVE2},
1522
{"shsubr_z_p_zz"_h, CPUFeatures::kSVE2},
1523
{"sli_z_zzi"_h, CPUFeatures::kSVE2},
1524
{"smaxp_z_p_zz"_h, CPUFeatures::kSVE2},
1525
{"sminp_z_p_zz"_h, CPUFeatures::kSVE2},
1526
{"smlalb_z_zzz"_h, CPUFeatures::kSVE2},
1527
{"smlalb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1528
{"smlalb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1529
{"smlalt_z_zzz"_h, CPUFeatures::kSVE2},
1530
{"smlalt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1531
{"smlalt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1532
{"smlslb_z_zzz"_h, CPUFeatures::kSVE2},
1533
{"smlslb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1534
{"smlslb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1535
{"smlslt_z_zzz"_h, CPUFeatures::kSVE2},
1536
{"smlslt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1537
{"smlslt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1538
{"smulh_z_zz"_h, CPUFeatures::kSVE2},
1539
{"smullb_z_zz"_h, CPUFeatures::kSVE2},
1540
{"smullb_z_zzi_d"_h, CPUFeatures::kSVE2},
1541
{"smullb_z_zzi_s"_h, CPUFeatures::kSVE2},
1542
{"smullt_z_zz"_h, CPUFeatures::kSVE2},
1543
{"smullt_z_zzi_d"_h, CPUFeatures::kSVE2},
1544
{"smullt_z_zzi_s"_h, CPUFeatures::kSVE2},
1545
{"splice_z_p_zz_con"_h, CPUFeatures::kSVE2},
1546
{"sqabs_z_p_z"_h, CPUFeatures::kSVE2},
1547
{"sqadd_z_p_zz"_h, CPUFeatures::kSVE2},
1548
{"sqcadd_z_zz"_h, CPUFeatures::kSVE2},
1549
{"sqdmlalb_z_zzz"_h, CPUFeatures::kSVE2},
1550
{"sqdmlalb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1551
{"sqdmlalb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1552
{"sqdmlalbt_z_zzz"_h, CPUFeatures::kSVE2},
1553
{"sqdmlalt_z_zzz"_h, CPUFeatures::kSVE2},
1554
{"sqdmlalt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1555
{"sqdmlalt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1556
{"sqdmlslb_z_zzz"_h, CPUFeatures::kSVE2},
1557
{"sqdmlslb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1558
{"sqdmlslb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1559
{"sqdmlslbt_z_zzz"_h, CPUFeatures::kSVE2},
1560
{"sqdmlslt_z_zzz"_h, CPUFeatures::kSVE2},
1561
{"sqdmlslt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1562
{"sqdmlslt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1563
{"sqdmulh_z_zz"_h, CPUFeatures::kSVE2},
1564
{"sqdmulh_z_zzi_d"_h, CPUFeatures::kSVE2},
1565
{"sqdmulh_z_zzi_h"_h, CPUFeatures::kSVE2},
1566
{"sqdmulh_z_zzi_s"_h, CPUFeatures::kSVE2},
1567
{"sqdmullb_z_zz"_h, CPUFeatures::kSVE2},
1568
{"sqdmullb_z_zzi_d"_h, CPUFeatures::kSVE2},
1569
{"sqdmullb_z_zzi_s"_h, CPUFeatures::kSVE2},
1570
{"sqdmullt_z_zz"_h, CPUFeatures::kSVE2},
1571
{"sqdmullt_z_zzi_d"_h, CPUFeatures::kSVE2},
1572
{"sqdmullt_z_zzi_s"_h, CPUFeatures::kSVE2},
1573
{"sqneg_z_p_z"_h, CPUFeatures::kSVE2},
1574
{"sqrdcmlah_z_zzz"_h, CPUFeatures::kSVE2},
1575
{"sqrdcmlah_z_zzzi_h"_h, CPUFeatures::kSVE2},
1576
{"sqrdcmlah_z_zzzi_s"_h, CPUFeatures::kSVE2},
1577
{"sqrdmlah_z_zzz"_h, CPUFeatures::kSVE2},
1578
{"sqrdmlah_z_zzzi_d"_h, CPUFeatures::kSVE2},
1579
{"sqrdmlah_z_zzzi_h"_h, CPUFeatures::kSVE2},
1580
{"sqrdmlah_z_zzzi_s"_h, CPUFeatures::kSVE2},
1581
{"sqrdmlsh_z_zzz"_h, CPUFeatures::kSVE2},
1582
{"sqrdmlsh_z_zzzi_d"_h, CPUFeatures::kSVE2},
1583
{"sqrdmlsh_z_zzzi_h"_h, CPUFeatures::kSVE2},
1584
{"sqrdmlsh_z_zzzi_s"_h, CPUFeatures::kSVE2},
1585
{"sqrdmulh_z_zz"_h, CPUFeatures::kSVE2},
1586
{"sqrdmulh_z_zzi_d"_h, CPUFeatures::kSVE2},
1587
{"sqrdmulh_z_zzi_h"_h, CPUFeatures::kSVE2},
1588
{"sqrdmulh_z_zzi_s"_h, CPUFeatures::kSVE2},
1589
{"sqrshl_z_p_zz"_h, CPUFeatures::kSVE2},
1590
{"sqrshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1591
{"sqrshrnb_z_zi"_h, CPUFeatures::kSVE2},
1592
{"sqrshrnt_z_zi"_h, CPUFeatures::kSVE2},
1593
{"sqrshrunb_z_zi"_h, CPUFeatures::kSVE2},
1594
{"sqrshrunt_z_zi"_h, CPUFeatures::kSVE2},
1595
{"sqshl_z_p_zi"_h, CPUFeatures::kSVE2},
1596
{"sqshl_z_p_zz"_h, CPUFeatures::kSVE2},
1597
{"sqshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1598
{"sqshlu_z_p_zi"_h, CPUFeatures::kSVE2},
1599
{"sqshrnb_z_zi"_h, CPUFeatures::kSVE2},
1600
{"sqshrnt_z_zi"_h, CPUFeatures::kSVE2},
1601
{"sqshrunb_z_zi"_h, CPUFeatures::kSVE2},
1602
{"sqshrunt_z_zi"_h, CPUFeatures::kSVE2},
1603
{"sqsub_z_p_zz"_h, CPUFeatures::kSVE2},
1604
{"sqsubr_z_p_zz"_h, CPUFeatures::kSVE2},
1605
{"sqxtnb_z_zz"_h, CPUFeatures::kSVE2},
1606
{"sqxtnt_z_zz"_h, CPUFeatures::kSVE2},
1607
{"sqxtunb_z_zz"_h, CPUFeatures::kSVE2},
1608
{"sqxtunt_z_zz"_h, CPUFeatures::kSVE2},
1609
{"srhadd_z_p_zz"_h, CPUFeatures::kSVE2},
1610
{"sri_z_zzi"_h, CPUFeatures::kSVE2},
1611
{"srshl_z_p_zz"_h, CPUFeatures::kSVE2},
1612
{"srshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1613
{"srshr_z_p_zi"_h, CPUFeatures::kSVE2},
1614
{"srsra_z_zi"_h, CPUFeatures::kSVE2},
1615
{"sshllb_z_zi"_h, CPUFeatures::kSVE2},
1616
{"sshllt_z_zi"_h, CPUFeatures::kSVE2},
1617
{"ssra_z_zi"_h, CPUFeatures::kSVE2},
1618
{"ssublb_z_zz"_h, CPUFeatures::kSVE2},
1619
{"ssublbt_z_zz"_h, CPUFeatures::kSVE2},
1620
{"ssublt_z_zz"_h, CPUFeatures::kSVE2},
1621
{"ssubltb_z_zz"_h, CPUFeatures::kSVE2},
1622
{"ssubwb_z_zz"_h, CPUFeatures::kSVE2},
1623
{"ssubwt_z_zz"_h, CPUFeatures::kSVE2},
1624
{"stnt1b_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1625
{"stnt1b_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1626
{"stnt1d_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1627
{"stnt1h_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1628
{"stnt1h_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1629
{"stnt1w_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2},
1630
{"stnt1w_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2},
1631
{"subhnb_z_zz"_h, CPUFeatures::kSVE2},
1632
{"subhnt_z_zz"_h, CPUFeatures::kSVE2},
1633
{"suqadd_z_p_zz"_h, CPUFeatures::kSVE2},
1634
{"tbl_z_zz_2"_h, CPUFeatures::kSVE2},
1635
{"tbx_z_zz"_h, CPUFeatures::kSVE2},
1636
{"uaba_z_zzz"_h, CPUFeatures::kSVE2},
1637
{"uabalb_z_zzz"_h, CPUFeatures::kSVE2},
1638
{"uabalt_z_zzz"_h, CPUFeatures::kSVE2},
1639
{"uabdlb_z_zz"_h, CPUFeatures::kSVE2},
1640
{"uabdlt_z_zz"_h, CPUFeatures::kSVE2},
1641
{"uadalp_z_p_z"_h, CPUFeatures::kSVE2},
1642
{"uaddlb_z_zz"_h, CPUFeatures::kSVE2},
1643
{"uaddlt_z_zz"_h, CPUFeatures::kSVE2},
1644
{"uaddwb_z_zz"_h, CPUFeatures::kSVE2},
1645
{"uaddwt_z_zz"_h, CPUFeatures::kSVE2},
1646
{"uhadd_z_p_zz"_h, CPUFeatures::kSVE2},
1647
{"uhsub_z_p_zz"_h, CPUFeatures::kSVE2},
1648
{"uhsubr_z_p_zz"_h, CPUFeatures::kSVE2},
1649
{"umaxp_z_p_zz"_h, CPUFeatures::kSVE2},
1650
{"uminp_z_p_zz"_h, CPUFeatures::kSVE2},
1651
{"umlalb_z_zzz"_h, CPUFeatures::kSVE2},
1652
{"umlalb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1653
{"umlalb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1654
{"umlalt_z_zzz"_h, CPUFeatures::kSVE2},
1655
{"umlalt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1656
{"umlalt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1657
{"umlslb_z_zzz"_h, CPUFeatures::kSVE2},
1658
{"umlslb_z_zzzi_d"_h, CPUFeatures::kSVE2},
1659
{"umlslb_z_zzzi_s"_h, CPUFeatures::kSVE2},
1660
{"umlslt_z_zzz"_h, CPUFeatures::kSVE2},
1661
{"umlslt_z_zzzi_d"_h, CPUFeatures::kSVE2},
1662
{"umlslt_z_zzzi_s"_h, CPUFeatures::kSVE2},
1663
{"umulh_z_zz"_h, CPUFeatures::kSVE2},
1664
{"umullb_z_zz"_h, CPUFeatures::kSVE2},
1665
{"umullb_z_zzi_d"_h, CPUFeatures::kSVE2},
1666
{"umullb_z_zzi_s"_h, CPUFeatures::kSVE2},
1667
{"umullt_z_zz"_h, CPUFeatures::kSVE2},
1668
{"umullt_z_zzi_d"_h, CPUFeatures::kSVE2},
1669
{"umullt_z_zzi_s"_h, CPUFeatures::kSVE2},
1670
{"uqadd_z_p_zz"_h, CPUFeatures::kSVE2},
1671
{"uqrshl_z_p_zz"_h, CPUFeatures::kSVE2},
1672
{"uqrshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1673
{"uqrshrnb_z_zi"_h, CPUFeatures::kSVE2},
1674
{"uqrshrnt_z_zi"_h, CPUFeatures::kSVE2},
1675
{"uqshl_z_p_zi"_h, CPUFeatures::kSVE2},
1676
{"uqshl_z_p_zz"_h, CPUFeatures::kSVE2},
1677
{"uqshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1678
{"uqshrnb_z_zi"_h, CPUFeatures::kSVE2},
1679
{"uqshrnt_z_zi"_h, CPUFeatures::kSVE2},
1680
{"uqsub_z_p_zz"_h, CPUFeatures::kSVE2},
1681
{"uqsubr_z_p_zz"_h, CPUFeatures::kSVE2},
1682
{"uqxtnb_z_zz"_h, CPUFeatures::kSVE2},
1683
{"uqxtnt_z_zz"_h, CPUFeatures::kSVE2},
1684
{"urecpe_z_p_z"_h, CPUFeatures::kSVE2},
1685
{"urhadd_z_p_zz"_h, CPUFeatures::kSVE2},
1686
{"urshl_z_p_zz"_h, CPUFeatures::kSVE2},
1687
{"urshlr_z_p_zz"_h, CPUFeatures::kSVE2},
1688
{"urshr_z_p_zi"_h, CPUFeatures::kSVE2},
1689
{"ursqrte_z_p_z"_h, CPUFeatures::kSVE2},
1690
{"ursra_z_zi"_h, CPUFeatures::kSVE2},
1691
{"ushllb_z_zi"_h, CPUFeatures::kSVE2},
1692
{"ushllt_z_zi"_h, CPUFeatures::kSVE2},
1693
{"usqadd_z_p_zz"_h, CPUFeatures::kSVE2},
1694
{"usra_z_zi"_h, CPUFeatures::kSVE2},
1695
{"usublb_z_zz"_h, CPUFeatures::kSVE2},
1696
{"usublt_z_zz"_h, CPUFeatures::kSVE2},
1697
{"usubwb_z_zz"_h, CPUFeatures::kSVE2},
1698
{"usubwt_z_zz"_h, CPUFeatures::kSVE2},
1699
{"whilege_p_p_rr"_h, CPUFeatures::kSVE2},
1700
{"whilegt_p_p_rr"_h, CPUFeatures::kSVE2},
1701
{"whilehi_p_p_rr"_h, CPUFeatures::kSVE2},
1702
{"whilehs_p_p_rr"_h, CPUFeatures::kSVE2},
1703
{"whilerw_p_rr"_h, CPUFeatures::kSVE2},
1704
{"whilewr_p_rr"_h, CPUFeatures::kSVE2},
1705
{"xar_z_zzi"_h, CPUFeatures::kSVE2},
1706
{"smmla_z_zzz"_h,
1707
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1708
{"ummla_z_zzz"_h,
1709
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1710
{"usmmla_z_zzz"_h,
1711
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1712
{"fmmla_z_zzz_s"_h,
1713
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF32MM)},
1714
{"fmmla_z_zzz_d"_h,
1715
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1716
{"smmla_asimdsame2_g"_h,
1717
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1718
{"ummla_asimdsame2_g"_h,
1719
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1720
{"usmmla_asimdsame2_g"_h,
1721
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1722
{"ld1row_z_p_bi_u32"_h,
1723
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1724
{"ld1row_z_p_br_contiguous"_h,
1725
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1726
{"ld1rod_z_p_bi_u64"_h,
1727
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1728
{"ld1rod_z_p_br_contiguous"_h,
1729
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1730
{"ld1rob_z_p_bi_u8"_h,
1731
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1732
{"ld1rob_z_p_br_contiguous"_h,
1733
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1734
{"ld1roh_z_p_bi_u16"_h,
1735
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1736
{"ld1roh_z_p_br_contiguous"_h,
1737
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)},
1738
{"usdot_asimdsame2_d"_h,
1739
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1740
{"sudot_asimdelem_d"_h,
1741
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1742
{"usdot_asimdelem_d"_h,
1743
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)},
1744
{"usdot_z_zzz_s"_h,
1745
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1746
{"usdot_z_zzzi_s"_h,
1747
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1748
{"sudot_z_zzzi_s"_h,
1749
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)},
1750
{"addg_64_addsub_immtags"_h, CPUFeatures::kMTE},
1751
{"gmi_64g_dp_2src"_h, CPUFeatures::kMTE},
1752
{"irg_64i_dp_2src"_h, CPUFeatures::kMTE},
1753
{"ldg_64loffset_ldsttags"_h, CPUFeatures::kMTE},
1754
{"st2g_64soffset_ldsttags"_h, CPUFeatures::kMTE},
1755
{"st2g_64spost_ldsttags"_h, CPUFeatures::kMTE},
1756
{"st2g_64spre_ldsttags"_h, CPUFeatures::kMTE},
1757
{"stgp_64_ldstpair_off"_h, CPUFeatures::kMTE},
1758
{"stgp_64_ldstpair_post"_h, CPUFeatures::kMTE},
1759
{"stgp_64_ldstpair_pre"_h, CPUFeatures::kMTE},
1760
{"stg_64soffset_ldsttags"_h, CPUFeatures::kMTE},
1761
{"stg_64spost_ldsttags"_h, CPUFeatures::kMTE},
1762
{"stg_64spre_ldsttags"_h, CPUFeatures::kMTE},
1763
{"stz2g_64soffset_ldsttags"_h, CPUFeatures::kMTE},
1764
{"stz2g_64spost_ldsttags"_h, CPUFeatures::kMTE},
1765
{"stz2g_64spre_ldsttags"_h, CPUFeatures::kMTE},
1766
{"stzg_64soffset_ldsttags"_h, CPUFeatures::kMTE},
1767
{"stzg_64spost_ldsttags"_h, CPUFeatures::kMTE},
1768
{"stzg_64spre_ldsttags"_h, CPUFeatures::kMTE},
1769
{"subg_64_addsub_immtags"_h, CPUFeatures::kMTE},
1770
{"subps_64s_dp_2src"_h, CPUFeatures::kMTE},
1771
{"subp_64s_dp_2src"_h, CPUFeatures::kMTE},
1772
{"cpyen_cpy_memcms"_h, CPUFeatures::kMOPS},
1773
{"cpyern_cpy_memcms"_h, CPUFeatures::kMOPS},
1774
{"cpyewn_cpy_memcms"_h, CPUFeatures::kMOPS},
1775
{"cpye_cpy_memcms"_h, CPUFeatures::kMOPS},
1776
{"cpyfen_cpy_memcms"_h, CPUFeatures::kMOPS},
1777
{"cpyfern_cpy_memcms"_h, CPUFeatures::kMOPS},
1778
{"cpyfewn_cpy_memcms"_h, CPUFeatures::kMOPS},
1779
{"cpyfe_cpy_memcms"_h, CPUFeatures::kMOPS},
1780
{"cpyfmn_cpy_memcms"_h, CPUFeatures::kMOPS},
1781
{"cpyfmrn_cpy_memcms"_h, CPUFeatures::kMOPS},
1782
{"cpyfmwn_cpy_memcms"_h, CPUFeatures::kMOPS},
1783
{"cpyfm_cpy_memcms"_h, CPUFeatures::kMOPS},
1784
{"cpyfpn_cpy_memcms"_h, CPUFeatures::kMOPS},
1785
{"cpyfprn_cpy_memcms"_h, CPUFeatures::kMOPS},
1786
{"cpyfpwn_cpy_memcms"_h, CPUFeatures::kMOPS},
1787
{"cpyfp_cpy_memcms"_h, CPUFeatures::kMOPS},
1788
{"cpymn_cpy_memcms"_h, CPUFeatures::kMOPS},
1789
{"cpymrn_cpy_memcms"_h, CPUFeatures::kMOPS},
1790
{"cpymwn_cpy_memcms"_h, CPUFeatures::kMOPS},
1791
{"cpym_cpy_memcms"_h, CPUFeatures::kMOPS},
1792
{"cpypn_cpy_memcms"_h, CPUFeatures::kMOPS},
1793
{"cpyprn_cpy_memcms"_h, CPUFeatures::kMOPS},
1794
{"cpypwn_cpy_memcms"_h, CPUFeatures::kMOPS},
1795
{"cpyp_cpy_memcms"_h, CPUFeatures::kMOPS},
1796
{"seten_set_memcms"_h, CPUFeatures::kMOPS},
1797
{"sete_set_memcms"_h, CPUFeatures::kMOPS},
1798
{"setgen_set_memcms"_h,
1799
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1800
{"setge_set_memcms"_h,
1801
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1802
{"setgmn_set_memcms"_h,
1803
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1804
{"setgm_set_memcms"_h,
1805
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1806
{"setgpn_set_memcms"_h,
1807
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1808
{"setgp_set_memcms"_h,
1809
CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)},
1810
{"setmn_set_memcms"_h, CPUFeatures::kMOPS},
1811
{"setm_set_memcms"_h, CPUFeatures::kMOPS},
1812
{"setpn_set_memcms"_h, CPUFeatures::kMOPS},
1813
{"setp_set_memcms"_h, CPUFeatures::kMOPS},
1814
{"abs_32_dp_1src"_h, CPUFeatures::kCSSC},
1815
{"abs_64_dp_1src"_h, CPUFeatures::kCSSC},
1816
{"cnt_32_dp_1src"_h, CPUFeatures::kCSSC},
1817
{"cnt_64_dp_1src"_h, CPUFeatures::kCSSC},
1818
{"ctz_32_dp_1src"_h, CPUFeatures::kCSSC},
1819
{"ctz_64_dp_1src"_h, CPUFeatures::kCSSC},
1820
{"smax_32_dp_2src"_h, CPUFeatures::kCSSC},
1821
{"smax_64_dp_2src"_h, CPUFeatures::kCSSC},
1822
{"smin_32_dp_2src"_h, CPUFeatures::kCSSC},
1823
{"smin_64_dp_2src"_h, CPUFeatures::kCSSC},
1824
{"umax_32_dp_2src"_h, CPUFeatures::kCSSC},
1825
{"umax_64_dp_2src"_h, CPUFeatures::kCSSC},
1826
{"umin_32_dp_2src"_h, CPUFeatures::kCSSC},
1827
{"umin_64_dp_2src"_h, CPUFeatures::kCSSC},
1828
{"smax_32_minmax_imm"_h, CPUFeatures::kCSSC},
1829
{"smax_64_minmax_imm"_h, CPUFeatures::kCSSC},
1830
{"smin_32_minmax_imm"_h, CPUFeatures::kCSSC},
1831
{"smin_64_minmax_imm"_h, CPUFeatures::kCSSC},
1832
{"umax_32u_minmax_imm"_h, CPUFeatures::kCSSC},
1833
{"umax_64u_minmax_imm"_h, CPUFeatures::kCSSC},
1834
{"umin_32u_minmax_imm"_h, CPUFeatures::kCSSC},
1835
{"umin_64u_minmax_imm"_h, CPUFeatures::kCSSC},
1836
};
1837
1838
if (features.count(form_hash_) > 0) {
1839
scope.Record(features[form_hash_]);
1840
}
1841
} else {
1842
(it->second)(this, instr);
1843
}
1844
}
1845
1846
} // namespace aarch64
1847
} // namespace vixl
1848
1849