1 // Copyright 2014, ARM Limited
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 "vixl/a64/instrument-a64.h"
28
29 namespace vixl {
30
Counter(const char * name,CounterType type)31 Counter::Counter(const char* name, CounterType type)
32 : count_(0), enabled_(false), type_(type) {
33 VIXL_ASSERT(name != NULL);
34 strncpy(name_, name, kCounterNameMaxLength);
35 }
36
37
Enable()38 void Counter::Enable() {
39 enabled_ = true;
40 }
41
42
Disable()43 void Counter::Disable() {
44 enabled_ = false;
45 }
46
47
IsEnabled()48 bool Counter::IsEnabled() {
49 return enabled_;
50 }
51
52
Increment()53 void Counter::Increment() {
54 if (enabled_) {
55 count_++;
56 }
57 }
58
59
count()60 uint64_t Counter::count() {
61 uint64_t result = count_;
62 if (type_ == Gauge) {
63 // If the counter is a Gauge, reset the count after reading.
64 count_ = 0;
65 }
66 return result;
67 }
68
69
name()70 const char* Counter::name() {
71 return name_;
72 }
73
74
type()75 CounterType Counter::type() {
76 return type_;
77 }
78
79
80 struct CounterDescriptor {
81 const char* name;
82 CounterType type;
83 };
84
85
86 static const CounterDescriptor kCounterList[] = {
87 {"Instruction", Cumulative},
88
89 {"Move Immediate", Gauge},
90 {"Add/Sub DP", Gauge},
91 {"Logical DP", Gauge},
92 {"Other Int DP", Gauge},
93 {"FP DP", Gauge},
94
95 {"Conditional Select", Gauge},
96 {"Conditional Compare", Gauge},
97
98 {"Unconditional Branch", Gauge},
99 {"Compare and Branch", Gauge},
100 {"Test and Branch", Gauge},
101 {"Conditional Branch", Gauge},
102
103 {"Load Integer", Gauge},
104 {"Load FP", Gauge},
105 {"Load Pair", Gauge},
106 {"Load Literal", Gauge},
107
108 {"Store Integer", Gauge},
109 {"Store FP", Gauge},
110 {"Store Pair", Gauge},
111
112 {"PC Addressing", Gauge},
113 {"Other", Gauge},
114 {"NEON", Gauge},
115 {"Crypto", Gauge}
116 };
117
118
Instrument(const char * datafile,uint64_t sample_period)119 Instrument::Instrument(const char* datafile, uint64_t sample_period)
120 : output_stream_(stdout), sample_period_(sample_period) {
121
122 // Set up the output stream. If datafile is non-NULL, use that file. If it
123 // can't be opened, or datafile is NULL, use stdout.
124 if (datafile != NULL) {
125 output_stream_ = fopen(datafile, "w");
126 if (output_stream_ == NULL) {
127 printf("Can't open output file %s. Using stdout.\n", datafile);
128 output_stream_ = stdout;
129 }
130 }
131
132 static const int num_counters =
133 sizeof(kCounterList) / sizeof(CounterDescriptor);
134
135 // Dump an instrumentation description comment at the top of the file.
136 fprintf(output_stream_, "# counters=%d\n", num_counters);
137 fprintf(output_stream_, "# sample_period=%" PRIu64 "\n", sample_period_);
138
139 // Construct Counter objects from counter description array.
140 for (int i = 0; i < num_counters; i++) {
141 Counter* counter = new Counter(kCounterList[i].name, kCounterList[i].type);
142 counters_.push_back(counter);
143 }
144
145 DumpCounterNames();
146 }
147
148
~Instrument()149 Instrument::~Instrument() {
150 // Dump any remaining instruction data to the output file.
151 DumpCounters();
152
153 // Free all the counter objects.
154 std::list<Counter*>::iterator it;
155 for (it = counters_.begin(); it != counters_.end(); it++) {
156 delete *it;
157 }
158
159 if (output_stream_ != stdout) {
160 fclose(output_stream_);
161 }
162 }
163
164
Update()165 void Instrument::Update() {
166 // Increment the instruction counter, and dump all counters if a sample period
167 // has elapsed.
168 static Counter* counter = GetCounter("Instruction");
169 VIXL_ASSERT(counter->type() == Cumulative);
170 counter->Increment();
171
172 if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) {
173 DumpCounters();
174 }
175 }
176
177
DumpCounters()178 void Instrument::DumpCounters() {
179 // Iterate through the counter objects, dumping their values to the output
180 // stream.
181 std::list<Counter*>::const_iterator it;
182 for (it = counters_.begin(); it != counters_.end(); it++) {
183 fprintf(output_stream_, "%" PRIu64 ",", (*it)->count());
184 }
185 fprintf(output_stream_, "\n");
186 fflush(output_stream_);
187 }
188
189
DumpCounterNames()190 void Instrument::DumpCounterNames() {
191 // Iterate through the counter objects, dumping the counter names to the
192 // output stream.
193 std::list<Counter*>::const_iterator it;
194 for (it = counters_.begin(); it != counters_.end(); it++) {
195 fprintf(output_stream_, "%s,", (*it)->name());
196 }
197 fprintf(output_stream_, "\n");
198 fflush(output_stream_);
199 }
200
201
HandleInstrumentationEvent(unsigned event)202 void Instrument::HandleInstrumentationEvent(unsigned event) {
203 switch (event) {
204 case InstrumentStateEnable: Enable(); break;
205 case InstrumentStateDisable: Disable(); break;
206 default: DumpEventMarker(event);
207 }
208 }
209
210
DumpEventMarker(unsigned marker)211 void Instrument::DumpEventMarker(unsigned marker) {
212 // Dumpan event marker to the output stream as a specially formatted comment
213 // line.
214 static Counter* counter = GetCounter("Instruction");
215
216 fprintf(output_stream_, "# %c%c @ %" PRId64 "\n", marker & 0xff,
217 (marker >> 8) & 0xff, counter->count());
218 }
219
220
GetCounter(const char * name)221 Counter* Instrument::GetCounter(const char* name) {
222 // Get a Counter object by name from the counter list.
223 std::list<Counter*>::const_iterator it;
224 for (it = counters_.begin(); it != counters_.end(); it++) {
225 if (strcmp((*it)->name(), name) == 0) {
226 return *it;
227 }
228 }
229
230 // A Counter by that name does not exist: print an error message to stderr
231 // and the output file, and exit.
232 static const char* error_message =
233 "# Error: Unknown counter \"%s\". Exiting.\n";
234 fprintf(stderr, error_message, name);
235 fprintf(output_stream_, error_message, name);
236 exit(1);
237 }
238
239
Enable()240 void Instrument::Enable() {
241 std::list<Counter*>::iterator it;
242 for (it = counters_.begin(); it != counters_.end(); it++) {
243 (*it)->Enable();
244 }
245 }
246
247
Disable()248 void Instrument::Disable() {
249 std::list<Counter*>::iterator it;
250 for (it = counters_.begin(); it != counters_.end(); it++) {
251 (*it)->Disable();
252 }
253 }
254
255
VisitPCRelAddressing(const Instruction * instr)256 void Instrument::VisitPCRelAddressing(const Instruction* instr) {
257 USE(instr);
258 Update();
259 static Counter* counter = GetCounter("PC Addressing");
260 counter->Increment();
261 }
262
263
VisitAddSubImmediate(const Instruction * instr)264 void Instrument::VisitAddSubImmediate(const Instruction* instr) {
265 USE(instr);
266 Update();
267 static Counter* counter = GetCounter("Add/Sub DP");
268 counter->Increment();
269 }
270
271
VisitLogicalImmediate(const Instruction * instr)272 void Instrument::VisitLogicalImmediate(const Instruction* instr) {
273 USE(instr);
274 Update();
275 static Counter* counter = GetCounter("Logical DP");
276 counter->Increment();
277 }
278
279
VisitMoveWideImmediate(const Instruction * instr)280 void Instrument::VisitMoveWideImmediate(const Instruction* instr) {
281 Update();
282 static Counter* counter = GetCounter("Move Immediate");
283
284 if (instr->IsMovn() && (instr->Rd() == kZeroRegCode)) {
285 unsigned imm = instr->ImmMoveWide();
286 HandleInstrumentationEvent(imm);
287 } else {
288 counter->Increment();
289 }
290 }
291
292
VisitBitfield(const Instruction * instr)293 void Instrument::VisitBitfield(const Instruction* instr) {
294 USE(instr);
295 Update();
296 static Counter* counter = GetCounter("Other Int DP");
297 counter->Increment();
298 }
299
300
VisitExtract(const Instruction * instr)301 void Instrument::VisitExtract(const Instruction* instr) {
302 USE(instr);
303 Update();
304 static Counter* counter = GetCounter("Other Int DP");
305 counter->Increment();
306 }
307
308
VisitUnconditionalBranch(const Instruction * instr)309 void Instrument::VisitUnconditionalBranch(const Instruction* instr) {
310 USE(instr);
311 Update();
312 static Counter* counter = GetCounter("Unconditional Branch");
313 counter->Increment();
314 }
315
316
VisitUnconditionalBranchToRegister(const Instruction * instr)317 void Instrument::VisitUnconditionalBranchToRegister(const Instruction* instr) {
318 USE(instr);
319 Update();
320 static Counter* counter = GetCounter("Unconditional Branch");
321 counter->Increment();
322 }
323
324
VisitCompareBranch(const Instruction * instr)325 void Instrument::VisitCompareBranch(const Instruction* instr) {
326 USE(instr);
327 Update();
328 static Counter* counter = GetCounter("Compare and Branch");
329 counter->Increment();
330 }
331
332
VisitTestBranch(const Instruction * instr)333 void Instrument::VisitTestBranch(const Instruction* instr) {
334 USE(instr);
335 Update();
336 static Counter* counter = GetCounter("Test and Branch");
337 counter->Increment();
338 }
339
340
VisitConditionalBranch(const Instruction * instr)341 void Instrument::VisitConditionalBranch(const Instruction* instr) {
342 USE(instr);
343 Update();
344 static Counter* counter = GetCounter("Conditional Branch");
345 counter->Increment();
346 }
347
348
VisitSystem(const Instruction * instr)349 void Instrument::VisitSystem(const Instruction* instr) {
350 USE(instr);
351 Update();
352 static Counter* counter = GetCounter("Other");
353 counter->Increment();
354 }
355
356
VisitException(const Instruction * instr)357 void Instrument::VisitException(const Instruction* instr) {
358 USE(instr);
359 Update();
360 static Counter* counter = GetCounter("Other");
361 counter->Increment();
362 }
363
364
InstrumentLoadStorePair(const Instruction * instr)365 void Instrument::InstrumentLoadStorePair(const Instruction* instr) {
366 static Counter* load_pair_counter = GetCounter("Load Pair");
367 static Counter* store_pair_counter = GetCounter("Store Pair");
368
369 if (instr->Mask(LoadStorePairLBit) != 0) {
370 load_pair_counter->Increment();
371 } else {
372 store_pair_counter->Increment();
373 }
374 }
375
376
VisitLoadStorePairPostIndex(const Instruction * instr)377 void Instrument::VisitLoadStorePairPostIndex(const Instruction* instr) {
378 Update();
379 InstrumentLoadStorePair(instr);
380 }
381
382
VisitLoadStorePairOffset(const Instruction * instr)383 void Instrument::VisitLoadStorePairOffset(const Instruction* instr) {
384 Update();
385 InstrumentLoadStorePair(instr);
386 }
387
388
VisitLoadStorePairPreIndex(const Instruction * instr)389 void Instrument::VisitLoadStorePairPreIndex(const Instruction* instr) {
390 Update();
391 InstrumentLoadStorePair(instr);
392 }
393
394
VisitLoadStorePairNonTemporal(const Instruction * instr)395 void Instrument::VisitLoadStorePairNonTemporal(const Instruction* instr) {
396 Update();
397 InstrumentLoadStorePair(instr);
398 }
399
400
VisitLoadStoreExclusive(const Instruction * instr)401 void Instrument::VisitLoadStoreExclusive(const Instruction* instr) {
402 USE(instr);
403 Update();
404 static Counter* counter = GetCounter("Other");
405 counter->Increment();
406 }
407
408
VisitLoadLiteral(const Instruction * instr)409 void Instrument::VisitLoadLiteral(const Instruction* instr) {
410 USE(instr);
411 Update();
412 static Counter* counter = GetCounter("Load Literal");
413 counter->Increment();
414 }
415
416
InstrumentLoadStore(const Instruction * instr)417 void Instrument::InstrumentLoadStore(const Instruction* instr) {
418 static Counter* load_int_counter = GetCounter("Load Integer");
419 static Counter* store_int_counter = GetCounter("Store Integer");
420 static Counter* load_fp_counter = GetCounter("Load FP");
421 static Counter* store_fp_counter = GetCounter("Store FP");
422
423 switch (instr->Mask(LoadStoreMask)) {
424 case STRB_w:
425 case STRH_w:
426 case STR_w:
427 VIXL_FALLTHROUGH();
428 case STR_x: store_int_counter->Increment(); break;
429 case STR_s:
430 VIXL_FALLTHROUGH();
431 case STR_d: store_fp_counter->Increment(); break;
432 case LDRB_w:
433 case LDRH_w:
434 case LDR_w:
435 case LDR_x:
436 case LDRSB_x:
437 case LDRSH_x:
438 case LDRSW_x:
439 case LDRSB_w:
440 VIXL_FALLTHROUGH();
441 case LDRSH_w: load_int_counter->Increment(); break;
442 case LDR_s:
443 VIXL_FALLTHROUGH();
444 case LDR_d: load_fp_counter->Increment(); break;
445 }
446 }
447
448
VisitLoadStoreUnscaledOffset(const Instruction * instr)449 void Instrument::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
450 Update();
451 InstrumentLoadStore(instr);
452 }
453
454
VisitLoadStorePostIndex(const Instruction * instr)455 void Instrument::VisitLoadStorePostIndex(const Instruction* instr) {
456 USE(instr);
457 Update();
458 InstrumentLoadStore(instr);
459 }
460
461
VisitLoadStorePreIndex(const Instruction * instr)462 void Instrument::VisitLoadStorePreIndex(const Instruction* instr) {
463 Update();
464 InstrumentLoadStore(instr);
465 }
466
467
VisitLoadStoreRegisterOffset(const Instruction * instr)468 void Instrument::VisitLoadStoreRegisterOffset(const Instruction* instr) {
469 Update();
470 InstrumentLoadStore(instr);
471 }
472
473
VisitLoadStoreUnsignedOffset(const Instruction * instr)474 void Instrument::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
475 Update();
476 InstrumentLoadStore(instr);
477 }
478
479
VisitLogicalShifted(const Instruction * instr)480 void Instrument::VisitLogicalShifted(const Instruction* instr) {
481 USE(instr);
482 Update();
483 static Counter* counter = GetCounter("Logical DP");
484 counter->Increment();
485 }
486
487
VisitAddSubShifted(const Instruction * instr)488 void Instrument::VisitAddSubShifted(const Instruction* instr) {
489 USE(instr);
490 Update();
491 static Counter* counter = GetCounter("Add/Sub DP");
492 counter->Increment();
493 }
494
495
VisitAddSubExtended(const Instruction * instr)496 void Instrument::VisitAddSubExtended(const Instruction* instr) {
497 USE(instr);
498 Update();
499 static Counter* counter = GetCounter("Add/Sub DP");
500 counter->Increment();
501 }
502
503
VisitAddSubWithCarry(const Instruction * instr)504 void Instrument::VisitAddSubWithCarry(const Instruction* instr) {
505 USE(instr);
506 Update();
507 static Counter* counter = GetCounter("Add/Sub DP");
508 counter->Increment();
509 }
510
511
VisitConditionalCompareRegister(const Instruction * instr)512 void Instrument::VisitConditionalCompareRegister(const Instruction* instr) {
513 USE(instr);
514 Update();
515 static Counter* counter = GetCounter("Conditional Compare");
516 counter->Increment();
517 }
518
519
VisitConditionalCompareImmediate(const Instruction * instr)520 void Instrument::VisitConditionalCompareImmediate(const Instruction* instr) {
521 USE(instr);
522 Update();
523 static Counter* counter = GetCounter("Conditional Compare");
524 counter->Increment();
525 }
526
527
VisitConditionalSelect(const Instruction * instr)528 void Instrument::VisitConditionalSelect(const Instruction* instr) {
529 USE(instr);
530 Update();
531 static Counter* counter = GetCounter("Conditional Select");
532 counter->Increment();
533 }
534
535
VisitDataProcessing1Source(const Instruction * instr)536 void Instrument::VisitDataProcessing1Source(const Instruction* instr) {
537 USE(instr);
538 Update();
539 static Counter* counter = GetCounter("Other Int DP");
540 counter->Increment();
541 }
542
543
VisitDataProcessing2Source(const Instruction * instr)544 void Instrument::VisitDataProcessing2Source(const Instruction* instr) {
545 USE(instr);
546 Update();
547 static Counter* counter = GetCounter("Other Int DP");
548 counter->Increment();
549 }
550
551
VisitDataProcessing3Source(const Instruction * instr)552 void Instrument::VisitDataProcessing3Source(const Instruction* instr) {
553 USE(instr);
554 Update();
555 static Counter* counter = GetCounter("Other Int DP");
556 counter->Increment();
557 }
558
559
VisitFPCompare(const Instruction * instr)560 void Instrument::VisitFPCompare(const Instruction* instr) {
561 USE(instr);
562 Update();
563 static Counter* counter = GetCounter("FP DP");
564 counter->Increment();
565 }
566
567
VisitFPConditionalCompare(const Instruction * instr)568 void Instrument::VisitFPConditionalCompare(const Instruction* instr) {
569 USE(instr);
570 Update();
571 static Counter* counter = GetCounter("Conditional Compare");
572 counter->Increment();
573 }
574
575
VisitFPConditionalSelect(const Instruction * instr)576 void Instrument::VisitFPConditionalSelect(const Instruction* instr) {
577 USE(instr);
578 Update();
579 static Counter* counter = GetCounter("Conditional Select");
580 counter->Increment();
581 }
582
583
VisitFPImmediate(const Instruction * instr)584 void Instrument::VisitFPImmediate(const Instruction* instr) {
585 USE(instr);
586 Update();
587 static Counter* counter = GetCounter("FP DP");
588 counter->Increment();
589 }
590
591
VisitFPDataProcessing1Source(const Instruction * instr)592 void Instrument::VisitFPDataProcessing1Source(const Instruction* instr) {
593 USE(instr);
594 Update();
595 static Counter* counter = GetCounter("FP DP");
596 counter->Increment();
597 }
598
599
VisitFPDataProcessing2Source(const Instruction * instr)600 void Instrument::VisitFPDataProcessing2Source(const Instruction* instr) {
601 USE(instr);
602 Update();
603 static Counter* counter = GetCounter("FP DP");
604 counter->Increment();
605 }
606
607
VisitFPDataProcessing3Source(const Instruction * instr)608 void Instrument::VisitFPDataProcessing3Source(const Instruction* instr) {
609 USE(instr);
610 Update();
611 static Counter* counter = GetCounter("FP DP");
612 counter->Increment();
613 }
614
615
VisitFPIntegerConvert(const Instruction * instr)616 void Instrument::VisitFPIntegerConvert(const Instruction* instr) {
617 USE(instr);
618 Update();
619 static Counter* counter = GetCounter("FP DP");
620 counter->Increment();
621 }
622
623
VisitFPFixedPointConvert(const Instruction * instr)624 void Instrument::VisitFPFixedPointConvert(const Instruction* instr) {
625 USE(instr);
626 Update();
627 static Counter* counter = GetCounter("FP DP");
628 counter->Increment();
629 }
630
631
VisitCrypto2RegSHA(const Instruction * instr)632 void Instrument::VisitCrypto2RegSHA(const Instruction* instr) {
633 USE(instr);
634 Update();
635 static Counter* counter = GetCounter("Crypto");
636 counter->Increment();
637 }
638
639
VisitCrypto3RegSHA(const Instruction * instr)640 void Instrument::VisitCrypto3RegSHA(const Instruction* instr) {
641 USE(instr);
642 Update();
643 static Counter* counter = GetCounter("Crypto");
644 counter->Increment();
645 }
646
647
VisitCryptoAES(const Instruction * instr)648 void Instrument::VisitCryptoAES(const Instruction* instr) {
649 USE(instr);
650 Update();
651 static Counter* counter = GetCounter("Crypto");
652 counter->Increment();
653 }
654
655
VisitNEON2RegMisc(const Instruction * instr)656 void Instrument::VisitNEON2RegMisc(const Instruction* instr) {
657 USE(instr);
658 Update();
659 static Counter* counter = GetCounter("NEON");
660 counter->Increment();
661 }
662
663
VisitNEON3Same(const Instruction * instr)664 void Instrument::VisitNEON3Same(const Instruction* instr) {
665 USE(instr);
666 Update();
667 static Counter* counter = GetCounter("NEON");
668 counter->Increment();
669 }
670
671
VisitNEON3Different(const Instruction * instr)672 void Instrument::VisitNEON3Different(const Instruction* instr) {
673 USE(instr);
674 Update();
675 static Counter* counter = GetCounter("NEON");
676 counter->Increment();
677 }
678
679
VisitNEONAcrossLanes(const Instruction * instr)680 void Instrument::VisitNEONAcrossLanes(const Instruction* instr) {
681 USE(instr);
682 Update();
683 static Counter* counter = GetCounter("NEON");
684 counter->Increment();
685 }
686
687
VisitNEONByIndexedElement(const Instruction * instr)688 void Instrument::VisitNEONByIndexedElement(const Instruction* instr) {
689 USE(instr);
690 Update();
691 static Counter* counter = GetCounter("NEON");
692 counter->Increment();
693 }
694
695
VisitNEONCopy(const Instruction * instr)696 void Instrument::VisitNEONCopy(const Instruction* instr) {
697 USE(instr);
698 Update();
699 static Counter* counter = GetCounter("NEON");
700 counter->Increment();
701 }
702
703
VisitNEONExtract(const Instruction * instr)704 void Instrument::VisitNEONExtract(const Instruction* instr) {
705 USE(instr);
706 Update();
707 static Counter* counter = GetCounter("NEON");
708 counter->Increment();
709 }
710
711
VisitNEONLoadStoreMultiStruct(const Instruction * instr)712 void Instrument::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
713 USE(instr);
714 Update();
715 static Counter* counter = GetCounter("NEON");
716 counter->Increment();
717 }
718
719
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)720 void Instrument::VisitNEONLoadStoreMultiStructPostIndex(
721 const Instruction* instr) {
722 USE(instr);
723 Update();
724 static Counter* counter = GetCounter("NEON");
725 counter->Increment();
726 }
727
728
VisitNEONLoadStoreSingleStruct(const Instruction * instr)729 void Instrument::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
730 USE(instr);
731 Update();
732 static Counter* counter = GetCounter("NEON");
733 counter->Increment();
734 }
735
736
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)737 void Instrument::VisitNEONLoadStoreSingleStructPostIndex(
738 const Instruction* instr) {
739 USE(instr);
740 Update();
741 static Counter* counter = GetCounter("NEON");
742 counter->Increment();
743 }
744
745
VisitNEONModifiedImmediate(const Instruction * instr)746 void Instrument::VisitNEONModifiedImmediate(const Instruction* instr) {
747 USE(instr);
748 Update();
749 static Counter* counter = GetCounter("NEON");
750 counter->Increment();
751 }
752
753
VisitNEONScalar2RegMisc(const Instruction * instr)754 void Instrument::VisitNEONScalar2RegMisc(const Instruction* instr) {
755 USE(instr);
756 Update();
757 static Counter* counter = GetCounter("NEON");
758 counter->Increment();
759 }
760
761
VisitNEONScalar3Diff(const Instruction * instr)762 void Instrument::VisitNEONScalar3Diff(const Instruction* instr) {
763 USE(instr);
764 Update();
765 static Counter* counter = GetCounter("NEON");
766 counter->Increment();
767 }
768
769
VisitNEONScalar3Same(const Instruction * instr)770 void Instrument::VisitNEONScalar3Same(const Instruction* instr) {
771 USE(instr);
772 Update();
773 static Counter* counter = GetCounter("NEON");
774 counter->Increment();
775 }
776
777
VisitNEONScalarByIndexedElement(const Instruction * instr)778 void Instrument::VisitNEONScalarByIndexedElement(const Instruction* instr) {
779 USE(instr);
780 Update();
781 static Counter* counter = GetCounter("NEON");
782 counter->Increment();
783 }
784
785
VisitNEONScalarCopy(const Instruction * instr)786 void Instrument::VisitNEONScalarCopy(const Instruction* instr) {
787 USE(instr);
788 Update();
789 static Counter* counter = GetCounter("NEON");
790 counter->Increment();
791 }
792
793
VisitNEONScalarPairwise(const Instruction * instr)794 void Instrument::VisitNEONScalarPairwise(const Instruction* instr) {
795 USE(instr);
796 Update();
797 static Counter* counter = GetCounter("NEON");
798 counter->Increment();
799 }
800
801
VisitNEONScalarShiftImmediate(const Instruction * instr)802 void Instrument::VisitNEONScalarShiftImmediate(const Instruction* instr) {
803 USE(instr);
804 Update();
805 static Counter* counter = GetCounter("NEON");
806 counter->Increment();
807 }
808
809
VisitNEONShiftImmediate(const Instruction * instr)810 void Instrument::VisitNEONShiftImmediate(const Instruction* instr) {
811 USE(instr);
812 Update();
813 static Counter* counter = GetCounter("NEON");
814 counter->Increment();
815 }
816
817
VisitNEONTable(const Instruction * instr)818 void Instrument::VisitNEONTable(const Instruction* instr) {
819 USE(instr);
820 Update();
821 static Counter* counter = GetCounter("NEON");
822 counter->Increment();
823 }
824
825
VisitNEONPerm(const Instruction * instr)826 void Instrument::VisitNEONPerm(const Instruction* instr) {
827 USE(instr);
828 Update();
829 static Counter* counter = GetCounter("NEON");
830 counter->Increment();
831 }
832
833
VisitUnallocated(const Instruction * instr)834 void Instrument::VisitUnallocated(const Instruction* instr) {
835 USE(instr);
836 Update();
837 static Counter* counter = GetCounter("Other");
838 counter->Increment();
839 }
840
841
VisitUnimplemented(const Instruction * instr)842 void Instrument::VisitUnimplemented(const Instruction* instr) {
843 USE(instr);
844 Update();
845 static Counter* counter = GetCounter("Other");
846 counter->Increment();
847 }
848
849
850 } // namespace vixl
851