xref: /aosp_15_r20/external/vixl/test/test-donkey.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2020, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi #include <regex>
28*f5c631daSSadaf Ebrahimi #include <set>
29*f5c631daSSadaf Ebrahimi 
30*f5c631daSSadaf Ebrahimi #include "aarch64/test-utils-aarch64.h"
31*f5c631daSSadaf Ebrahimi 
32*f5c631daSSadaf Ebrahimi using namespace vixl;
33*f5c631daSSadaf Ebrahimi using namespace vixl::aarch64;
34*f5c631daSSadaf Ebrahimi 
35*f5c631daSSadaf Ebrahimi #define __ masm->
36*f5c631daSSadaf Ebrahimi 
37*f5c631daSSadaf Ebrahimi class InstructionReporter : public DecoderVisitor {
38*f5c631daSSadaf Ebrahimi  public:
InstructionReporter()39*f5c631daSSadaf Ebrahimi   InstructionReporter() : DecoderVisitor(kNonConstVisitor) {}
40*f5c631daSSadaf Ebrahimi 
Visit(Metadata * metadata,const Instruction * instr)41*f5c631daSSadaf Ebrahimi   void Visit(Metadata *metadata, const Instruction *instr) VIXL_OVERRIDE {
42*f5c631daSSadaf Ebrahimi     USE(instr);
43*f5c631daSSadaf Ebrahimi     instr_form_ = (*metadata)["form"];
44*f5c631daSSadaf Ebrahimi   }
45*f5c631daSSadaf Ebrahimi 
MoveForm()46*f5c631daSSadaf Ebrahimi   std::string MoveForm() { return std::move(instr_form_); }
47*f5c631daSSadaf Ebrahimi 
48*f5c631daSSadaf Ebrahimi  private:
49*f5c631daSSadaf Ebrahimi   std::string instr_form_;
50*f5c631daSSadaf Ebrahimi };
51*f5c631daSSadaf Ebrahimi 
Mutate(Instr base)52*f5c631daSSadaf Ebrahimi Instr Mutate(Instr base) {
53*f5c631daSSadaf Ebrahimi   Instr result = base;
54*f5c631daSSadaf Ebrahimi   while ((result == base) || (result == 0)) {
55*f5c631daSSadaf Ebrahimi     // Flip two bits somewhere in the most-significant 27.
56*f5c631daSSadaf Ebrahimi     for (int i = 0; i < 2; i++) {
57*f5c631daSSadaf Ebrahimi       uint32_t pos = 5 + ((lrand48() >> 20) % 27);
58*f5c631daSSadaf Ebrahimi       result = result ^ (1 << pos);
59*f5c631daSSadaf Ebrahimi     }
60*f5c631daSSadaf Ebrahimi 
61*f5c631daSSadaf Ebrahimi     // Always flip one of the low five bits, as that's where the destination
62*f5c631daSSadaf Ebrahimi     // register is often encoded.
63*f5c631daSSadaf Ebrahimi     uint32_t dst_pos = (lrand48() >> 20) % 5;
64*f5c631daSSadaf Ebrahimi     result = result ^ (1 << dst_pos);
65*f5c631daSSadaf Ebrahimi   }
66*f5c631daSSadaf Ebrahimi   return result;
67*f5c631daSSadaf Ebrahimi }
68*f5c631daSSadaf Ebrahimi 
69*f5c631daSSadaf Ebrahimi #ifndef VIXL_INCLUDE_SIMULATOR_AARCH64
main(void)70*f5c631daSSadaf Ebrahimi int main(void) {
71*f5c631daSSadaf Ebrahimi   printf("Test donkey requires a simulator build to be useful.\n");
72*f5c631daSSadaf Ebrahimi   return 0;
73*f5c631daSSadaf Ebrahimi }
74*f5c631daSSadaf Ebrahimi #else
main(int argc,char ** argv)75*f5c631daSSadaf Ebrahimi int main(int argc, char **argv) {
76*f5c631daSSadaf Ebrahimi   if ((argc < 3) || (argc > 5)) {
77*f5c631daSSadaf Ebrahimi     printf(
78*f5c631daSSadaf Ebrahimi         "Usage: test-donkey <instruction form regex> <number of instructions "
79*f5c631daSSadaf Ebrahimi         "to emit in test> <encoding generation manner> <input data type>\n"
80*f5c631daSSadaf Ebrahimi         "  regex - ECMAScript (C++11) regular expression to match instruction "
81*f5c631daSSadaf Ebrahimi         "form\n"
82*f5c631daSSadaf Ebrahimi         "  encoding=random - use rng only to select new instructions\n"
83*f5c631daSSadaf Ebrahimi         "    (can take longer, but gives better coverage for disparate "
84*f5c631daSSadaf Ebrahimi         "encodings)\n"
85*f5c631daSSadaf Ebrahimi         "  encoding=`initial hex` - hex encoding of first instruction in test, "
86*f5c631daSSadaf Ebrahimi         "eg. 1234abcd\n"
87*f5c631daSSadaf Ebrahimi         "  input data type - used to specify the data type of generating "
88*f5c631daSSadaf Ebrahimi         "input, e.g. input=fp, default set to integer type\n"
89*f5c631daSSadaf Ebrahimi         "  command examples :\n"
90*f5c631daSSadaf Ebrahimi         "  ./test-donkey \"fml[as]l[bt]\" 50 encoding=random input=fp\n"
91*f5c631daSSadaf Ebrahimi         "  ./test-donkey \"fml[as]l[bt]\" 30 input=int\n");
92*f5c631daSSadaf Ebrahimi     exit(1);
93*f5c631daSSadaf Ebrahimi   }
94*f5c631daSSadaf Ebrahimi 
95*f5c631daSSadaf Ebrahimi   // Use LC-RNG only to select instructions.
96*f5c631daSSadaf Ebrahimi   bool random_only = false;
97*f5c631daSSadaf Ebrahimi 
98*f5c631daSSadaf Ebrahimi   std::string target_re = argv[1];
99*f5c631daSSadaf Ebrahimi   uint32_t count = static_cast<uint32_t>(strtoul(argv[2], NULL, 10));
100*f5c631daSSadaf Ebrahimi   uint32_t cmdline_encoding = 0;
101*f5c631daSSadaf Ebrahimi   InputSet input_set = kIntInputSet;
102*f5c631daSSadaf Ebrahimi   if (argc > 3) {
103*f5c631daSSadaf Ebrahimi     // The arguments of instruction pattern and the number of generating
104*f5c631daSSadaf Ebrahimi     // instructions are processed.
105*f5c631daSSadaf Ebrahimi     int32_t i = 3;
106*f5c631daSSadaf Ebrahimi     std::string argv_s(argv[i]);
107*f5c631daSSadaf Ebrahimi     if (argv_s.find("encoding=") != std::string::npos) {
108*f5c631daSSadaf Ebrahimi       char *c = argv[i];
109*f5c631daSSadaf Ebrahimi       c += 9;
110*f5c631daSSadaf Ebrahimi       if (strcmp(c, "random") == 0) {
111*f5c631daSSadaf Ebrahimi         random_only = true;
112*f5c631daSSadaf Ebrahimi       } else {
113*f5c631daSSadaf Ebrahimi         cmdline_encoding = static_cast<uint32_t>(strtoul(c, NULL, 16));
114*f5c631daSSadaf Ebrahimi       }
115*f5c631daSSadaf Ebrahimi       i++;
116*f5c631daSSadaf Ebrahimi     }
117*f5c631daSSadaf Ebrahimi 
118*f5c631daSSadaf Ebrahimi     if ((argc > 4) || (i == 3)) {
119*f5c631daSSadaf Ebrahimi       argv_s = std::string(argv[i]);
120*f5c631daSSadaf Ebrahimi       if (argv_s.find("input=") != std::string::npos) {
121*f5c631daSSadaf Ebrahimi         char *c = argv[i];
122*f5c631daSSadaf Ebrahimi         c += 6;
123*f5c631daSSadaf Ebrahimi         if (strcmp(c, "fp") == 0) {
124*f5c631daSSadaf Ebrahimi           input_set = kFpInputSet;
125*f5c631daSSadaf Ebrahimi         } else {
126*f5c631daSSadaf Ebrahimi           VIXL_ASSERT(strcmp(c, "int") == 0);
127*f5c631daSSadaf Ebrahimi         }
128*f5c631daSSadaf Ebrahimi         i++;
129*f5c631daSSadaf Ebrahimi       }
130*f5c631daSSadaf Ebrahimi     }
131*f5c631daSSadaf Ebrahimi 
132*f5c631daSSadaf Ebrahimi     // Ensure all arguments have been processed.
133*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(argc == i);
134*f5c631daSSadaf Ebrahimi   }
135*f5c631daSSadaf Ebrahimi 
136*f5c631daSSadaf Ebrahimi   srand48(42);
137*f5c631daSSadaf Ebrahimi 
138*f5c631daSSadaf Ebrahimi   MacroAssembler masm;
139*f5c631daSSadaf Ebrahimi   masm.GetCPUFeatures()->Combine(CPUFeatures::kSVE);
140*f5c631daSSadaf Ebrahimi 
141*f5c631daSSadaf Ebrahimi   std::map<int, Simulator *> sim_vl;
142*f5c631daSSadaf Ebrahimi   for (int i = 128; i <= 2048; i += 128) {
143*f5c631daSSadaf Ebrahimi     sim_vl[i] = new Simulator(new Decoder());
144*f5c631daSSadaf Ebrahimi     sim_vl[i]->SetVectorLengthInBits(i);
145*f5c631daSSadaf Ebrahimi   }
146*f5c631daSSadaf Ebrahimi 
147*f5c631daSSadaf Ebrahimi   char buffer[256];
148*f5c631daSSadaf Ebrahimi   Decoder trial_decoder;
149*f5c631daSSadaf Ebrahimi   Disassembler disasm(buffer, sizeof(buffer));
150*f5c631daSSadaf Ebrahimi   InstructionReporter reporter;
151*f5c631daSSadaf Ebrahimi   trial_decoder.AppendVisitor(&reporter);
152*f5c631daSSadaf Ebrahimi   trial_decoder.AppendVisitor(&disasm);
153*f5c631daSSadaf Ebrahimi 
154*f5c631daSSadaf Ebrahimi   using InstrData = struct {
155*f5c631daSSadaf Ebrahimi     Instr inst;
156*f5c631daSSadaf Ebrahimi     std::string disasm;
157*f5c631daSSadaf Ebrahimi     uint32_t state_hash;
158*f5c631daSSadaf Ebrahimi   };
159*f5c631daSSadaf Ebrahimi   std::vector<InstrData> useful_insts;
160*f5c631daSSadaf Ebrahimi 
161*f5c631daSSadaf Ebrahimi   // Seen states are only considered for vl128. It's assumed that a new state
162*f5c631daSSadaf Ebrahimi   // for vl128 implies a new state for all other vls.
163*f5c631daSSadaf Ebrahimi   std::set<uint32_t> seen_states;
164*f5c631daSSadaf Ebrahimi   uint32_t state_hash;
165*f5c631daSSadaf Ebrahimi 
166*f5c631daSSadaf Ebrahimi   std::map<int, uint32_t> initial_state_vl;
167*f5c631daSSadaf Ebrahimi   std::map<int, uint32_t> state_hash_vl;
168*f5c631daSSadaf Ebrahimi 
169*f5c631daSSadaf Ebrahimi   // Compute hash of the initial state of the machine.
170*f5c631daSSadaf Ebrahimi   Label test;
171*f5c631daSSadaf Ebrahimi   masm.Bind(&test);
172*f5c631daSSadaf Ebrahimi   masm.PushCalleeSavedRegisters();
173*f5c631daSSadaf Ebrahimi   SetInitialMachineState(&masm, input_set);
174*f5c631daSSadaf Ebrahimi   ComputeMachineStateHash(&masm, &state_hash);
175*f5c631daSSadaf Ebrahimi   masm.PopCalleeSavedRegisters();
176*f5c631daSSadaf Ebrahimi   masm.Ret();
177*f5c631daSSadaf Ebrahimi   masm.FinalizeCode();
178*f5c631daSSadaf Ebrahimi   masm.GetBuffer()->SetExecutable();
179*f5c631daSSadaf Ebrahimi 
180*f5c631daSSadaf Ebrahimi   for (std::pair<int, Simulator *> s : sim_vl) {
181*f5c631daSSadaf Ebrahimi     s.second->RunFrom(masm.GetLabelAddress<Instruction *>(&test));
182*f5c631daSSadaf Ebrahimi     initial_state_vl[s.first] = state_hash;
183*f5c631daSSadaf Ebrahimi     if (s.first == 128) seen_states.insert(state_hash);
184*f5c631daSSadaf Ebrahimi   }
185*f5c631daSSadaf Ebrahimi 
186*f5c631daSSadaf Ebrahimi   masm.GetBuffer()->SetWritable();
187*f5c631daSSadaf Ebrahimi   masm.Reset();
188*f5c631daSSadaf Ebrahimi 
189*f5c631daSSadaf Ebrahimi   // Count number of failed instructions, in order to allow changing instruction
190*f5c631daSSadaf Ebrahimi   // candidate strategy.
191*f5c631daSSadaf Ebrahimi   int miss_count = 0;
192*f5c631daSSadaf Ebrahimi 
193*f5c631daSSadaf Ebrahimi   while (useful_insts.size() < count) {
194*f5c631daSSadaf Ebrahimi     miss_count++;
195*f5c631daSSadaf Ebrahimi 
196*f5c631daSSadaf Ebrahimi     Instr inst;
197*f5c631daSSadaf Ebrahimi     if (cmdline_encoding != 0) {
198*f5c631daSSadaf Ebrahimi       // Initial instruction encoding supplied on the command line.
199*f5c631daSSadaf Ebrahimi       inst = cmdline_encoding;
200*f5c631daSSadaf Ebrahimi       cmdline_encoding = 0;
201*f5c631daSSadaf Ebrahimi     } else if (useful_insts.empty() || random_only || (miss_count > 10000)) {
202*f5c631daSSadaf Ebrahimi       // LCG-random instruction.
203*f5c631daSSadaf Ebrahimi       inst = static_cast<Instr>(mrand48());
204*f5c631daSSadaf Ebrahimi     } else {
205*f5c631daSSadaf Ebrahimi       // Instruction based on mutation of last successful instruction.
206*f5c631daSSadaf Ebrahimi       inst = Mutate(useful_insts.back().inst);
207*f5c631daSSadaf Ebrahimi     }
208*f5c631daSSadaf Ebrahimi 
209*f5c631daSSadaf Ebrahimi     trial_decoder.Decode(reinterpret_cast<Instruction *>(&inst));
210*f5c631daSSadaf Ebrahimi     if (std::regex_search(reporter.MoveForm(), std::regex(target_re))) {
211*f5c631daSSadaf Ebrahimi       // Disallow "unimplemented" instructions.
212*f5c631daSSadaf Ebrahimi       std::string buffer_s(buffer);
213*f5c631daSSadaf Ebrahimi       if (buffer_s.find("unimplemented") != std::string::npos) continue;
214*f5c631daSSadaf Ebrahimi 
215*f5c631daSSadaf Ebrahimi       // Disallow instructions with "sp" in their arguments, as we don't support
216*f5c631daSSadaf Ebrahimi       // instructions operating on memory, and the OS expects sp to be valid for
217*f5c631daSSadaf Ebrahimi       // signal handlers, etc.
218*f5c631daSSadaf Ebrahimi       size_t space = buffer_s.find(' ');
219*f5c631daSSadaf Ebrahimi       if ((space != std::string::npos) &&
220*f5c631daSSadaf Ebrahimi           (buffer_s.substr(space).find("sp") != std::string::npos))
221*f5c631daSSadaf Ebrahimi         continue;
222*f5c631daSSadaf Ebrahimi 
223*f5c631daSSadaf Ebrahimi       fprintf(stderr, "Trying 0x%08x (%s)\n", inst, buffer);
224*f5c631daSSadaf Ebrahimi 
225*f5c631daSSadaf Ebrahimi       // TODO: factorise this code into a CalculateState helper function.
226*f5c631daSSadaf Ebrahimi 
227*f5c631daSSadaf Ebrahimi       // Initialise the machine to a known state.
228*f5c631daSSadaf Ebrahimi       masm.PushCalleeSavedRegisters();
229*f5c631daSSadaf Ebrahimi       SetInitialMachineState(&masm, input_set);
230*f5c631daSSadaf Ebrahimi 
231*f5c631daSSadaf Ebrahimi       {
232*f5c631daSSadaf Ebrahimi         ExactAssemblyScope scope(&masm,
233*f5c631daSSadaf Ebrahimi                                  (useful_insts.size() + 1) * kInstructionSize);
234*f5c631daSSadaf Ebrahimi 
235*f5c631daSSadaf Ebrahimi         // Emit any instructions already found to move the state to somewhere
236*f5c631daSSadaf Ebrahimi         // new.
237*f5c631daSSadaf Ebrahimi         for (const InstrData &i : useful_insts) {
238*f5c631daSSadaf Ebrahimi           masm.dci(i.inst);
239*f5c631daSSadaf Ebrahimi         }
240*f5c631daSSadaf Ebrahimi 
241*f5c631daSSadaf Ebrahimi         // Try a new instruction.
242*f5c631daSSadaf Ebrahimi         masm.dci(inst);
243*f5c631daSSadaf Ebrahimi       }
244*f5c631daSSadaf Ebrahimi 
245*f5c631daSSadaf Ebrahimi       // Compute the new state of the machine.
246*f5c631daSSadaf Ebrahimi       ComputeMachineStateHash(&masm, &state_hash);
247*f5c631daSSadaf Ebrahimi       masm.PopCalleeSavedRegisters();
248*f5c631daSSadaf Ebrahimi       masm.Ret();
249*f5c631daSSadaf Ebrahimi       masm.FinalizeCode();
250*f5c631daSSadaf Ebrahimi       masm.GetBuffer()->SetExecutable();
251*f5c631daSSadaf Ebrahimi 
252*f5c631daSSadaf Ebrahimi       // Try the new instruction for VL128.
253*f5c631daSSadaf Ebrahimi       sim_vl[128]->RunFrom(masm.GetLabelAddress<Instruction *>(&test));
254*f5c631daSSadaf Ebrahimi       state_hash_vl[128] = state_hash;
255*f5c631daSSadaf Ebrahimi 
256*f5c631daSSadaf Ebrahimi       if (seen_states.count(state_hash_vl[128]) == 0) {
257*f5c631daSSadaf Ebrahimi         // A new state! Run for all VLs, record it, add the instruction to the
258*f5c631daSSadaf Ebrahimi         // list of useful ones.
259*f5c631daSSadaf Ebrahimi 
260*f5c631daSSadaf Ebrahimi         for (std::pair<int, Simulator *> s : sim_vl) {
261*f5c631daSSadaf Ebrahimi           if (s.first == 128) continue;
262*f5c631daSSadaf Ebrahimi           s.second->RunFrom(masm.GetLabelAddress<Instruction *>(&test));
263*f5c631daSSadaf Ebrahimi           state_hash_vl[s.first] = state_hash;
264*f5c631daSSadaf Ebrahimi         }
265*f5c631daSSadaf Ebrahimi 
266*f5c631daSSadaf Ebrahimi         seen_states.insert(state_hash_vl[128]);
267*f5c631daSSadaf Ebrahimi         useful_insts.push_back({inst, buffer, state_hash_vl[128]});
268*f5c631daSSadaf Ebrahimi         miss_count = 0;
269*f5c631daSSadaf Ebrahimi       } else {
270*f5c631daSSadaf Ebrahimi         // Machine already reached here. Probably not an interesting
271*f5c631daSSadaf Ebrahimi         // instruction. NB. it's possible for an instruction to reach the same
272*f5c631daSSadaf Ebrahimi         // machine state as two or more others, but for these purposes, let's
273*f5c631daSSadaf Ebrahimi         // call that not useful.
274*f5c631daSSadaf Ebrahimi         fprintf(stderr,
275*f5c631daSSadaf Ebrahimi                 "Already reached state 0x%08x, skipping 0x%08x, miss_count "
276*f5c631daSSadaf Ebrahimi                 "%d\n",
277*f5c631daSSadaf Ebrahimi                 state_hash_vl[128],
278*f5c631daSSadaf Ebrahimi                 inst,
279*f5c631daSSadaf Ebrahimi                 miss_count);
280*f5c631daSSadaf Ebrahimi       }
281*f5c631daSSadaf Ebrahimi 
282*f5c631daSSadaf Ebrahimi       // Restart generation.
283*f5c631daSSadaf Ebrahimi       masm.GetBuffer()->SetWritable();
284*f5c631daSSadaf Ebrahimi       masm.Reset();
285*f5c631daSSadaf Ebrahimi     }
286*f5c631daSSadaf Ebrahimi   }
287*f5c631daSSadaf Ebrahimi 
288*f5c631daSSadaf Ebrahimi   // Emit test case based on identified instructions and associated hashes.
289*f5c631daSSadaf Ebrahimi   printf("TEST_SVE(sve2_%s) {\n", target_re.c_str());
290*f5c631daSSadaf Ebrahimi   printf(
291*f5c631daSSadaf Ebrahimi       "  SVE_SETUP_WITH_FEATURES(CPUFeatures::kSVE, CPUFeatures::kSVE2, "
292*f5c631daSSadaf Ebrahimi       "CPUFeatures::kNEON, "
293*f5c631daSSadaf Ebrahimi       "CPUFeatures::kCRC32);\n");
294*f5c631daSSadaf Ebrahimi   printf("  START();\n\n");
295*f5c631daSSadaf Ebrahimi   printf((input_set == kFpInputSet)
296*f5c631daSSadaf Ebrahimi              ? "  SetInitialMachineState(&masm, kFpInputSet);\n"
297*f5c631daSSadaf Ebrahimi              : "  SetInitialMachineState(&masm);\n");
298*f5c631daSSadaf Ebrahimi   printf("  // state = 0x%08x\n\n", initial_state_vl[128]);
299*f5c631daSSadaf Ebrahimi 
300*f5c631daSSadaf Ebrahimi   printf("  {\n");
301*f5c631daSSadaf Ebrahimi   printf("    ExactAssemblyScope scope(&masm, %lu * kInstructionSize);\n",
302*f5c631daSSadaf Ebrahimi          useful_insts.size());
303*f5c631daSSadaf Ebrahimi   for (InstrData &i : useful_insts) {
304*f5c631daSSadaf Ebrahimi     printf("    __ dci(0x%08x);  // %s\n", i.inst, i.disasm.c_str());
305*f5c631daSSadaf Ebrahimi     printf("    // vl128 state = 0x%08x\n", i.state_hash);
306*f5c631daSSadaf Ebrahimi   }
307*f5c631daSSadaf Ebrahimi   printf("  }\n\n");
308*f5c631daSSadaf Ebrahimi   printf("  uint32_t state;\n");
309*f5c631daSSadaf Ebrahimi   printf("  ComputeMachineStateHash(&masm, &state);\n");
310*f5c631daSSadaf Ebrahimi   printf("  __ Mov(x0, reinterpret_cast<uint64_t>(&state));\n");
311*f5c631daSSadaf Ebrahimi   printf("  __ Ldr(w0, MemOperand(x0));\n\n");
312*f5c631daSSadaf Ebrahimi   printf("  END();\n");
313*f5c631daSSadaf Ebrahimi   printf("  if (CAN_RUN()) {\n");
314*f5c631daSSadaf Ebrahimi   printf("    RUN();\n");
315*f5c631daSSadaf Ebrahimi   printf("    uint32_t expected_hashes[] = {\n");
316*f5c631daSSadaf Ebrahimi   for (std::pair<int, uint32_t> h : state_hash_vl) {
317*f5c631daSSadaf Ebrahimi     printf("    0x%08x,\n", h.second);
318*f5c631daSSadaf Ebrahimi   }
319*f5c631daSSadaf Ebrahimi   printf("    };\n");
320*f5c631daSSadaf Ebrahimi   printf(
321*f5c631daSSadaf Ebrahimi       "    ASSERT_EQUAL_64(expected_hashes[core.GetSVELaneCount(kQRegSize) - "
322*f5c631daSSadaf Ebrahimi       "1], x0);\n");
323*f5c631daSSadaf Ebrahimi   printf("  }\n}\n");
324*f5c631daSSadaf Ebrahimi 
325*f5c631daSSadaf Ebrahimi   return 0;
326*f5c631daSSadaf Ebrahimi }
327*f5c631daSSadaf Ebrahimi #endif
328