xref: /aosp_15_r20/art/compiler/utils/assembler_test.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
18 #define ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
19 
20 #include "assembler.h"
21 
22 #include <sys/stat.h>
23 
24 #include <cstdio>
25 #include <cstdlib>
26 #include <fstream>
27 #include <iterator>
28 
29 #include "base/array_ref.h"
30 #include "base/macros.h"
31 #include "base/malloc_arena_pool.h"
32 #include "assembler_test_base.h"
33 #include "common_runtime_test.h"  // For ScratchFile
34 
35 namespace art HIDDEN {
36 
37 // Helper for a constexpr string length.
38 constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
39   return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
40 }
41 
42 enum class RegisterView {  // private
43   kUsePrimaryName,
44   kUseSecondaryName,
45   kUseTertiaryName,
46   kUseQuaternaryName,
47 };
48 
49 // For use in the template as the default type to get a nonvector registers version.
50 struct NoVectorRegs {};
51 
52 template<typename Ass,
53          typename Addr,
54          typename Reg,
55          typename FPReg,
56          typename Imm,
57          typename VecReg = NoVectorRegs>
58 class AssemblerTest : public AssemblerTestBase {
59  public:
GetAssembler()60   Ass* GetAssembler() {
61     return assembler_.get();
62   }
63 
64   using TestFn = std::string (*)(AssemblerTest *, Ass *);
65 
DriverFn(TestFn f,const std::string & test_name)66   void DriverFn(TestFn f, const std::string& test_name) {
67     DriverWrapper(f(this, assembler_.get()), test_name);
68   }
69 
70   // This driver assumes the assembler has already been called.
DriverStr(const std::string & assembly_string,const std::string & test_name)71   void DriverStr(const std::string& assembly_string, const std::string& test_name) {
72     DriverWrapper(assembly_string, test_name);
73   }
74 
75   //
76   // Register repeats.
77   //
78 
RepeatR(void (Ass::* f)(Reg),const std::string & fmt)79   std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
80     return RepeatTemplatedRegister<Reg>(f,
81         GetRegisters(),
82         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
83         fmt);
84   }
85 
Repeatr(void (Ass::* f)(Reg),const std::string & fmt)86   std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
87     return RepeatTemplatedRegister<Reg>(f,
88         GetRegisters(),
89         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
90         fmt);
91   }
92 
93   std::string RepeatRR(void (Ass::*f)(Reg, Reg),
94                        const std::string& fmt,
95                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
96     return RepeatTemplatedRegisters<Reg, Reg>(f,
97         GetRegisters(),
98         GetRegisters(),
99         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
100         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
101         fmt,
102         except);
103   }
104 
RepeatRRNoDupes(void (Ass::* f)(Reg,Reg),const std::string & fmt)105   std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
106     return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
107         GetRegisters(),
108         GetRegisters(),
109         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
110         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
111         fmt);
112   }
113 
114   std::string Repeatrr(void (Ass::*f)(Reg, Reg),
115                        const std::string& fmt,
116                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
117     return RepeatTemplatedRegisters<Reg, Reg>(f,
118         GetRegisters(),
119         GetRegisters(),
120         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
121         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
122         fmt,
123         except);
124   }
125 
126   std::string Repeatww(void (Ass::*f)(Reg, Reg),
127                        const std::string& fmt,
128                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
129     return RepeatTemplatedRegisters<Reg, Reg>(f,
130         GetRegisters(),
131         GetRegisters(),
132         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
133         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
134         fmt,
135         except);
136   }
137 
138   std::string Repeatbb(void (Ass::*f)(Reg, Reg),
139                        const std::string& fmt,
140                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
141     return RepeatTemplatedRegisters<Reg, Reg>(f,
142         GetRegisters(),
143         GetRegisters(),
144         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
145         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
146         fmt,
147         except);
148   }
149 
RepeatRRR(void (Ass::* f)(Reg,Reg,Reg),const std::string & fmt)150   std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
151     return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
152         GetRegisters(),
153         GetRegisters(),
154         GetRegisters(),
155         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
156         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
157         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
158         fmt);
159   }
160 
161   std::string Repeatrb(void (Ass::*f)(Reg, Reg),
162                        const std::string& fmt,
163                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
164     return RepeatTemplatedRegisters<Reg, Reg>(f,
165         GetRegisters(),
166         GetRegisters(),
167         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
168         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
169         fmt,
170         except);
171   }
172 
173   std::string RepeatRr(void (Ass::*f)(Reg, Reg),
174                        const std::string& fmt,
175                        const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
176     return RepeatTemplatedRegisters<Reg, Reg>(f,
177         GetRegisters(),
178         GetRegisters(),
179         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
180         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
181         fmt,
182         except);
183   }
184 
RepeatRI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)185   std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
186     return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
187   }
188 
RepeatrI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)189   std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
190     return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
191   }
192 
RepeatwI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)193   std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
194     return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
195   }
196 
RepeatbI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)197   std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
198     return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
199   }
200 
201   template <typename Reg1, typename Reg2, typename ImmType>
202   std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
203                                               int imm_bits,
204                                               ArrayRef<const Reg1> reg1_registers,
205                                               ArrayRef<const Reg2> reg2_registers,
206                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
207                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
208                                               const std::string& fmt,
209                                               int bias = 0,
210                                               int multiplier = 1) {
211     std::string str;
212     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
213 
214     for (auto reg1 : reg1_registers) {
215       for (auto reg2 : reg2_registers) {
216         for (int64_t imm : imms) {
217           ImmType new_imm = CreateImmediate(imm);
218           if (f != nullptr) {
219             (assembler_.get()->*f)(reg1, reg2, new_imm * multiplier + bias);
220           }
221           std::string base = fmt;
222 
223           ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
224           ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
225           ReplaceImm(imm, bias, multiplier, &base);
226 
227           str += base;
228           str += "\n";
229         }
230       }
231     }
232     return str;
233   }
234 
235   template <typename Reg1, typename Reg2, typename Reg3, typename ImmType>
RepeatTemplatedRegistersImmBits(void (Ass::* f)(Reg1,Reg2,Reg3,ImmType),int imm_bits,ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),const std::string & fmt,int bias)236   std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType),
237                                               int imm_bits,
238                                               ArrayRef<const Reg1> reg1_registers,
239                                               ArrayRef<const Reg2> reg2_registers,
240                                               ArrayRef<const Reg3> reg3_registers,
241                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
242                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
243                                               std::string (AssemblerTest::*GetName3)(const Reg3&),
244                                               const std::string& fmt,
245                                               int bias) {
246     std::string str;
247     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
248 
249     for (auto reg1 : reg1_registers) {
250       for (auto reg2 : reg2_registers) {
251         for (auto reg3 : reg3_registers) {
252           for (int64_t imm : imms) {
253             ImmType new_imm = CreateImmediate(imm);
254             if (f != nullptr) {
255               (assembler_.get()->*f)(reg1, reg2, reg3, new_imm + bias);
256             }
257             std::string base = fmt;
258 
259             ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
260             ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
261             ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base);
262             ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
263 
264             str += base;
265             str += "\n";
266           }
267         }
268       }
269     }
270     return str;
271   }
272 
273   template <typename ImmType, typename Reg1, typename Reg2>
RepeatTemplatedImmBitsRegisters(void (Ass::* f)(ImmType,Reg1,Reg2),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),int imm_bits,const std::string & fmt)274   std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
275                                               ArrayRef<const Reg1> reg1_registers,
276                                               ArrayRef<const Reg2> reg2_registers,
277                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
278                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
279                                               int imm_bits,
280                                               const std::string& fmt) {
281     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
282 
283     WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
284 
285     std::string str;
286     for (auto reg1 : reg1_registers) {
287       for (auto reg2 : reg2_registers) {
288         for (int64_t imm : imms) {
289           ImmType new_imm = CreateImmediate(imm);
290           if (f != nullptr) {
291             (assembler_.get()->*f)(new_imm, reg1, reg2);
292           }
293           std::string base = fmt;
294 
295           ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
296           ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
297           ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
298 
299           str += base;
300           str += "\n";
301         }
302       }
303     }
304     return str;
305   }
306 
307   template <typename RegType, typename ImmType>
RepeatTemplatedRegisterImmBits(void (Ass::* f)(RegType,ImmType),int imm_bits,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt,int bias)308   std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
309                                              int imm_bits,
310                                              ArrayRef<const RegType> registers,
311                                              std::string (AssemblerTest::*GetName)(const RegType&),
312                                              const std::string& fmt,
313                                              int bias) {
314     std::string str;
315     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
316 
317     for (auto reg : registers) {
318       for (int64_t imm : imms) {
319         ImmType new_imm = CreateImmediate(imm);
320         if (f != nullptr) {
321           (assembler_.get()->*f)(reg, new_imm + bias);
322         }
323         std::string base = fmt;
324 
325         ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base);
326         ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
327 
328         str += base;
329         str += "\n";
330       }
331     }
332     return str;
333   }
334 
335   template <typename RegType, typename ImmType>
RepeatTemplatedRegisterImmBitsShift(void (Ass::* f)(RegType,ImmType),int imm_bits,int shift,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt,int bias)336   std::string RepeatTemplatedRegisterImmBitsShift(
337       void (Ass::*f)(RegType, ImmType),
338       int imm_bits,
339       int shift,
340       ArrayRef<const RegType> registers,
341       std::string (AssemblerTest::*GetName)(const RegType&),
342       const std::string& fmt,
343       int bias) {
344     std::string str;
345     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
346 
347     for (auto reg : registers) {
348       for (int64_t imm : imms) {
349         ImmType new_imm = CreateImmediate(imm);
350         if (f != nullptr) {
351           (assembler_.get()->*f)(reg, new_imm + bias);
352         }
353         std::string base = fmt;
354 
355         ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base);
356         ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
357 
358         str += base;
359         str += "\n";
360       }
361     }
362     return str;
363   }
364 
365   template <typename ImmType>
366   std::string RepeatTemplatedImmBitsShift(
367       void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
368     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
369 
370     WarnOnCombinations(imms.size());
371 
372     std::string str;
373 
374     for (int64_t imm : imms) {
375       ImmType new_imm = CreateImmediate(imm);
376       if (f != nullptr) {
377         (assembler_.get()->*f)(new_imm + bias);
378       }
379       std::string base = fmt;
380 
381       ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
382 
383       str += base;
384       str += "\n";
385     }
386     return str;
387   }
388 
389   template <typename Reg1, typename Reg2, typename ImmType>
390   std::string RepeatTemplatedRegistersImmBitsShift(
391       void (Ass::*f)(Reg1, Reg2, ImmType),
392       int imm_bits,
393       int shift,
394       ArrayRef<const Reg1> reg1_registers,
395       ArrayRef<const Reg2> reg2_registers,
396       std::string (AssemblerTest::*GetName1)(const Reg1&),
397       std::string (AssemblerTest::*GetName2)(const Reg2&),
398       const std::string& fmt,
399       int bias = 0,
400       int multiplier = 1) {
401     std::string str;
402     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
403 
404     for (auto reg1 : reg1_registers) {
405       for (auto reg2 : reg2_registers) {
406         for (int64_t imm : imms) {
407           ImmType new_imm = CreateImmediate(imm);
408           if (f != nullptr) {
409             (assembler_.get()->*f)(reg1, reg2, new_imm * multiplier + bias);
410           }
411           std::string base = fmt;
412 
413           ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
414           ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
415           ReplaceImm(imm, bias, multiplier, &base);
416 
417           str += base;
418           str += "\n";
419         }
420       }
421     }
422     return str;
423   }
424 
425   template <typename ImmType>
426   std::string RepeatIbS(
427       void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
428     return RepeatTemplatedImmBitsShift<ImmType>(f, imm_bits, shift, fmt, bias);
429   }
430 
431   template <typename ImmType>
432   std::string RepeatRIbS(
433       void (Ass::*f)(Reg, ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
434     return RepeatTemplatedRegisterImmBitsShift<Reg, ImmType>(
435         f,
436         imm_bits,
437         shift,
438         GetRegisters(),
439         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
440         fmt,
441         bias);
442   }
443 
444   template <typename ImmType>
445   std::string RepeatRRIbS(void (Ass::*f)(Reg, Reg, ImmType),
446                           int imm_bits,
447                           int shift,
448                           const std::string& fmt,
449                           int bias = 0) {
450     return RepeatTemplatedRegistersImmBitsShift<Reg, Reg, ImmType>(
451         f,
452         imm_bits,
453         shift,
454         GetRegisters(),
455         GetRegisters(),
456         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
457         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
458         fmt,
459         bias);
460   }
461 
462   template <typename ImmType>
463   std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
464                          int imm_bits,
465                          const std::string& fmt,
466                          int bias = 0) {
467     return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
468         imm_bits,
469         GetRegisters(),
470         GetRegisters(),
471         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
472         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
473         fmt,
474         bias);
475   }
476 
477   template <typename ImmType>
478   std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
479                           int imm_bits,
480                           const std::string& fmt,
481                           int bias = 0) {
482     return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
483         imm_bits,
484         GetRegisters(),
485         GetRegisters(),
486         GetRegisters(),
487         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
488         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
489         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
490         fmt,
491         bias);
492   }
493 
494   template <typename ImmType>
495   std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
496     return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
497         imm_bits,
498         GetRegisters(),
499         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
500         fmt,
501         bias);
502   }
503 
504   template <typename ImmType>
505   std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
506                          int imm_bits,
507                          const std::string& fmt,
508                          int bias = 0) {
509     return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
510         imm_bits,
511         GetFPRegisters(),
512         GetRegisters(),
513         &AssemblerTest::GetFPRegName,
514         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
515         fmt,
516         bias);
517   }
518 
RepeatFF(void (Ass::* f)(FPReg,FPReg),const std::string & fmt)519   std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
520     return RepeatTemplatedRegisters<FPReg, FPReg>(f,
521                                                   GetFPRegisters(),
522                                                   GetFPRegisters(),
523                                                   &AssemblerTest::GetFPRegName,
524                                                   &AssemblerTest::GetFPRegName,
525                                                   fmt);
526   }
527 
RepeatFFF(void (Ass::* f)(FPReg,FPReg,FPReg),const std::string & fmt)528   std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
529     return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
530                                                          GetFPRegisters(),
531                                                          GetFPRegisters(),
532                                                          GetFPRegisters(),
533                                                          &AssemblerTest::GetFPRegName,
534                                                          &AssemblerTest::GetFPRegName,
535                                                          &AssemblerTest::GetFPRegName,
536                                                          fmt);
537   }
538 
RepeatFFFF(void (Ass::* f)(FPReg,FPReg,FPReg,FPReg),const std::string & fmt)539   std::string RepeatFFFF(void (Ass::*f)(FPReg, FPReg, FPReg, FPReg), const std::string& fmt) {
540     return RepeatTemplatedRegisters<FPReg, FPReg, FPReg, FPReg>(f,
541                                                                 GetFPRegisters(),
542                                                                 GetFPRegisters(),
543                                                                 GetFPRegisters(),
544                                                                 GetFPRegisters(),
545                                                                 &AssemblerTest::GetFPRegName,
546                                                                 &AssemblerTest::GetFPRegName,
547                                                                 &AssemblerTest::GetFPRegName,
548                                                                 &AssemblerTest::GetFPRegName,
549                                                                 fmt);
550   }
551 
RepeatFFR(void (Ass::* f)(FPReg,FPReg,Reg),const std::string & fmt)552   std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
553     return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
554         f,
555         GetFPRegisters(),
556         GetFPRegisters(),
557         GetRegisters(),
558         &AssemblerTest::GetFPRegName,
559         &AssemblerTest::GetFPRegName,
560         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
561         fmt);
562   }
563 
RepeatFFI(void (Ass::* f)(FPReg,FPReg,const Imm &),size_t imm_bytes,const std::string & fmt)564   std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
565                         size_t imm_bytes,
566                         const std::string& fmt) {
567     return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
568                                                      GetFPRegisters(),
569                                                      GetFPRegisters(),
570                                                      &AssemblerTest::GetFPRegName,
571                                                      &AssemblerTest::GetFPRegName,
572                                                      imm_bytes,
573                                                      fmt);
574   }
575 
576   template <typename ImmType>
RepeatFFIb(void (Ass::* f)(FPReg,FPReg,ImmType),int imm_bits,const std::string & fmt)577   std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
578                          int imm_bits,
579                          const std::string& fmt) {
580     return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
581                                                                   imm_bits,
582                                                                   GetFPRegisters(),
583                                                                   GetFPRegisters(),
584                                                                   &AssemblerTest::GetFPRegName,
585                                                                   &AssemblerTest::GetFPRegName,
586                                                                   fmt);
587   }
588 
589   template <typename ImmType>
RepeatIbFF(void (Ass::* f)(ImmType,FPReg,FPReg),int imm_bits,const std::string & fmt)590   std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
591                          int imm_bits,
592                          const std::string& fmt) {
593     return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
594                                                                   GetFPRegisters(),
595                                                                   GetFPRegisters(),
596                                                                   &AssemblerTest::GetFPRegName,
597                                                                   &AssemblerTest::GetFPRegName,
598                                                                   imm_bits,
599                                                                   fmt);
600   }
601 
RepeatRFF(void (Ass::* f)(Reg,FPReg,FPReg),const std::string & fmt)602   std::string RepeatRFF(void (Ass::*f)(Reg, FPReg, FPReg), const std::string& fmt) {
603     return RepeatTemplatedRegisters<Reg, FPReg, FPReg>(
604         f,
605         GetRegisters(),
606         GetFPRegisters(),
607         GetFPRegisters(),
608         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
609         &AssemblerTest::GetFPRegName,
610         &AssemblerTest::GetFPRegName,
611         fmt);
612   }
613 
614   template <typename ImmType>
RepeatRFIb(void (Ass::* f)(Reg,FPReg,ImmType),int imm_bits,const std::string & fmt)615   std::string RepeatRFIb(void (Ass::*f)(Reg, FPReg, ImmType),
616                          int imm_bits,
617                          const std::string& fmt) {
618     return RepeatTemplatedRegistersImmBits<Reg, FPReg, ImmType>(
619         f,
620         imm_bits,
621         GetRegisters(),
622         GetFPRegisters(),
623         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
624         &AssemblerTest::GetFPRegName,
625         fmt);
626   }
627 
RepeatFR(void (Ass::* f)(FPReg,Reg),const std::string & fmt)628   std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
629     return RepeatTemplatedRegisters<FPReg, Reg>(f,
630         GetFPRegisters(),
631         GetRegisters(),
632         &AssemblerTest::GetFPRegName,
633         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
634         fmt);
635   }
636 
RepeatFr(void (Ass::* f)(FPReg,Reg),const std::string & fmt)637   std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
638     return RepeatTemplatedRegisters<FPReg, Reg>(f,
639         GetFPRegisters(),
640         GetRegisters(),
641         &AssemblerTest::GetFPRegName,
642         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
643         fmt);
644   }
645 
RepeatRF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)646   std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
647     return RepeatTemplatedRegisters<Reg, FPReg>(f,
648         GetRegisters(),
649         GetFPRegisters(),
650         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
651         &AssemblerTest::GetFPRegName,
652         fmt);
653   }
654 
RepeatrF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)655   std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
656     return RepeatTemplatedRegisters<Reg, FPReg>(f,
657         GetRegisters(),
658         GetFPRegisters(),
659         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
660         &AssemblerTest::GetFPRegName,
661         fmt);
662   }
663 
664   std::string RepeatI(void (Ass::*f)(const Imm&),
665                       size_t imm_bytes,
666                       const std::string& fmt,
667                       bool as_uint = false) {
668     std::string str;
669     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
670 
671     WarnOnCombinations(imms.size());
672 
673     for (int64_t imm : imms) {
674       Imm new_imm = CreateImmediate(imm);
675       if (f != nullptr) {
676         (assembler_.get()->*f)(new_imm);
677       }
678       std::string base = fmt;
679 
680       ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
681 
682       str += base;
683       str += "\n";
684     }
685     return str;
686   }
687 
RepeatV(void (Ass::* f)(VecReg),const std::string & fmt)688   std::string RepeatV(void (Ass::*f)(VecReg), const std::string& fmt) {
689     return RepeatTemplatedRegister<VecReg>(
690         f, GetVectorRegisters(), &AssemblerTest::GetVecRegName, fmt);
691   }
692 
RepeatVV(void (Ass::* f)(VecReg,VecReg),const std::string & fmt)693   std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
694     return RepeatTemplatedRegisters<VecReg, VecReg>(f,
695                                                     GetVectorRegisters(),
696                                                     GetVectorRegisters(),
697                                                     &AssemblerTest::GetVecRegName,
698                                                     &AssemblerTest::GetVecRegName,
699                                                     fmt);
700   }
701 
RepeatVVV(void (Ass::* f)(VecReg,VecReg,VecReg),const std::string & fmt)702   std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
703     return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
704                                                             GetVectorRegisters(),
705                                                             GetVectorRegisters(),
706                                                             GetVectorRegisters(),
707                                                             &AssemblerTest::GetVecRegName,
708                                                             &AssemblerTest::GetVecRegName,
709                                                             &AssemblerTest::GetVecRegName,
710                                                             fmt);
711   }
712 
RepeatVVR(void (Ass::* f)(VecReg,VecReg,Reg),const std::string & fmt)713   std::string RepeatVVR(void (Ass::*f)(VecReg, VecReg, Reg), const std::string& fmt) {
714     return RepeatTemplatedRegisters<VecReg, VecReg, Reg>(
715         f,
716         GetVectorRegisters(),
717         GetVectorRegisters(),
718         GetRegisters(),
719         &AssemblerTest::GetVecRegName,
720         &AssemblerTest::GetVecRegName,
721         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
722         fmt);
723   }
724 
RepeatVR(void (Ass::* f)(VecReg,Reg),const std::string & fmt)725   std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
726     return RepeatTemplatedRegisters<VecReg, Reg>(
727         f,
728         GetVectorRegisters(),
729         GetRegisters(),
730         &AssemblerTest::GetVecRegName,
731         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
732         fmt);
733   }
734 
RepeatVF(void (Ass::* f)(VecReg,FPReg),const std::string & fmt)735   std::string RepeatVF(void (Ass::*f)(VecReg, FPReg), const std::string& fmt) {
736     return RepeatTemplatedRegisters<VecReg, FPReg>(f,
737                                                    GetVectorRegisters(),
738                                                    GetFPRegisters(),
739                                                    &AssemblerTest::GetVecRegName,
740                                                    &AssemblerTest::GetFPRegName,
741                                                    fmt);
742   }
743 
RepeatFV(void (Ass::* f)(FPReg,VecReg),const std::string & fmt)744   std::string RepeatFV(void (Ass::*f)(FPReg, VecReg), const std::string& fmt) {
745     return RepeatTemplatedRegisters<FPReg, VecReg>(f,
746                                                    GetFPRegisters(),
747                                                    GetVectorRegisters(),
748                                                    &AssemblerTest::GetFPRegName,
749                                                    &AssemblerTest::GetVecRegName,
750                                                    fmt);
751   }
752 
RepeatRV(void (Ass::* f)(Reg,VecReg),const std::string & fmt)753   std::string RepeatRV(void (Ass::*f)(Reg, VecReg), const std::string& fmt) {
754     return RepeatTemplatedRegisters<Reg, VecReg>(
755         f,
756         GetRegisters(),
757         GetVectorRegisters(),
758         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
759         &AssemblerTest::GetVecRegName,
760         fmt);
761   }
762 
763   template <typename ImmType>
764   std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
765                         int imm_bits,
766                         std::string fmt,
767                         int bias = 0) {
768     return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
769                                                            imm_bits,
770                                                            GetVectorRegisters(),
771                                                            &AssemblerTest::GetVecRegName,
772                                                            fmt,
773                                                            bias);
774   }
775 
776   template <typename ImmType>
777   std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
778                          int imm_bits,
779                          const std::string& fmt,
780                          int bias = 0,
781                          int multiplier = 1) {
782     return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
783         f,
784         imm_bits,
785         GetVectorRegisters(),
786         GetRegisters(),
787         &AssemblerTest::GetVecRegName,
788         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
789         fmt,
790         bias,
791         multiplier);
792   }
793 
794   template <typename ImmType>
795   std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
796                          int imm_bits,
797                          const std::string& fmt,
798                          int bias = 0,
799                          int multiplier = 1) {
800     return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
801         f,
802         imm_bits,
803         GetRegisters(),
804         GetVectorRegisters(),
805         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
806         &AssemblerTest::GetVecRegName,
807         fmt,
808         bias,
809         multiplier);
810   }
811 
812   template <typename ImmType>
813   std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
814                          int imm_bits,
815                          const std::string& fmt,
816                          int bias = 0) {
817     return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
818                                                                     imm_bits,
819                                                                     GetVectorRegisters(),
820                                                                     GetVectorRegisters(),
821                                                                     &AssemblerTest::GetVecRegName,
822                                                                     &AssemblerTest::GetVecRegName,
823                                                                     fmt,
824                                                                     bias);
825   }
826 
827   // The following functions are public so that TestFn can use them...
828 
829   // Returns a vector of address used by any of the repeat methods
830   // involving an "A" (e.g. RepeatA).
831   virtual std::vector<Addr> GetAddresses() = 0;
832 
833   // Returns a vector of registers used by any of the repeat methods
834   // involving an "R" (e.g. RepeatR).
835   virtual ArrayRef<const Reg> GetRegisters() = 0;
836 
837   // Returns a vector of fp-registers used by any of the repeat methods
838   // involving an "F" (e.g. RepeatFF).
GetFPRegisters()839   virtual ArrayRef<const FPReg> GetFPRegisters() {
840     UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
841     UNREACHABLE();
842   }
843 
844   // Returns a vector of dedicated simd-registers used by any of the repeat
845   // methods involving an "V" (e.g. RepeatVV).
GetVectorRegisters()846   virtual ArrayRef<const VecReg> GetVectorRegisters() {
847     UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
848     UNREACHABLE();
849   }
850 
851   // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
GetSecondaryRegisterName(const Reg & reg)852   virtual std::string GetSecondaryRegisterName([[maybe_unused]] const Reg& reg) {
853     UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
854     UNREACHABLE();
855   }
856 
857   // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
GetTertiaryRegisterName(const Reg & reg)858   virtual std::string GetTertiaryRegisterName([[maybe_unused]] const Reg& reg) {
859     UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
860     UNREACHABLE();
861   }
862 
863   // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
GetQuaternaryRegisterName(const Reg & reg)864   virtual std::string GetQuaternaryRegisterName([[maybe_unused]] const Reg& reg) {
865     UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
866     UNREACHABLE();
867   }
868 
GetRegisterName(const Reg & reg)869   std::string GetRegisterName(const Reg& reg) {
870     return GetRegName<RegisterView::kUsePrimaryName>(reg);
871   }
872 
873  protected:
AssemblerTest()874   AssemblerTest() {}
875 
SetUp()876   void SetUp() override {
877     AssemblerTestBase::SetUp();
878     allocator_.reset(new ArenaAllocator(&pool_));
879     assembler_.reset(CreateAssembler(allocator_.get()));
880     SetUpHelpers();
881   }
882 
TearDown()883   void TearDown() override {
884     AssemblerTestBase::TearDown();
885     assembler_.reset();
886     allocator_.reset();
887   }
888 
889   // Override this to set up any architecture-specific things, e.g., CPU revision.
CreateAssembler(ArenaAllocator * allocator)890   virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
891     return new (allocator) Ass(allocator);
892   }
893 
894   // Override this to set up any architecture-specific things, e.g., register vectors.
SetUpHelpers()895   virtual void SetUpHelpers() {}
896 
897   // Create a couple of immediate values up to the number of bytes given.
898   virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
899     std::vector<int64_t> res;
900     res.push_back(0);
901     if (!as_uint) {
902       res.push_back(-1);
903     } else {
904       res.push_back(0xFF);
905     }
906     res.push_back(0x12);
907     if (imm_bytes >= 2) {
908       res.push_back(0x1234);
909       if (!as_uint) {
910         res.push_back(-0x1234);
911       } else {
912         res.push_back(0xFFFF);
913       }
914       if (imm_bytes >= 4) {
915         res.push_back(0x12345678);
916         if (!as_uint) {
917           res.push_back(-0x12345678);
918         } else {
919           res.push_back(0xFFFFFFFF);
920         }
921         if (imm_bytes >= 6) {
922           res.push_back(0x123456789ABC);
923           if (!as_uint) {
924             res.push_back(-0x123456789ABC);
925           }
926           if (imm_bytes >= 8) {
927             res.push_back(0x123456789ABCDEF0);
928             if (!as_uint) {
929               res.push_back(-0x123456789ABCDEF0);
930             } else {
931               res.push_back(0xFFFFFFFFFFFFFFFF);
932             }
933           }
934         }
935       }
936     }
937     return res;
938   }
939 
940   const int kMaxBitsExhaustiveTest = 8;
941 
942   // Create a couple of immediate values up to the number of bits given.
943   virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits,
944                                                          bool as_uint = false,
945                                                          int shift = 0) {
946     CHECK_GT(imm_bits, 0);
947     CHECK_LE(imm_bits, 64);
948     std::vector<int64_t> res;
949 
950     if (imm_bits <= kMaxBitsExhaustiveTest) {
951       if (as_uint) {
952         for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
953           res.push_back(static_cast<int64_t>(i << shift));
954         }
955       } else {
956         for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
957           res.push_back(i << shift);
958         }
959       }
960     } else {
961       if (as_uint) {
962         for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
963              i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
964              i++) {
965           res.push_back(static_cast<int64_t>(i << shift));
966         }
967         for (int i = 0; i <= imm_bits; i++) {
968           uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
969                        ((MaxInt<uint64_t>(imm_bits) -
970                         (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
971                         * i / imm_bits);
972           res.push_back(static_cast<int64_t>(j << shift));
973         }
974       } else {
975         for (int i = 0; i <= imm_bits; i++) {
976           int64_t j = MinInt<int64_t>(imm_bits) +
977                       ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
978                          MinInt<int64_t>(imm_bits))
979                         * i) / imm_bits);
980           res.push_back(static_cast<int64_t>(j << shift));
981         }
982         for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
983              i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
984              i++) {
985           res.push_back(static_cast<int64_t>(i << shift));
986         }
987         for (int i = 0; i <= imm_bits; i++) {
988           int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
989                       ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
990                        * i / imm_bits);
991           res.push_back(static_cast<int64_t>(j << shift));
992         }
993       }
994     }
995 
996     return res;
997   }
998 
999   // Create an immediate from the specific value.
1000   virtual Imm CreateImmediate(int64_t imm_value) = 0;
1001 
1002   //
1003   // Addresses repeats.
1004   //
1005 
1006   // Repeats over addresses provided by fixture.
RepeatA(void (Ass::* f)(const Addr &),const std::string & fmt)1007   std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
1008     return RepeatA(f, GetAddresses(), fmt);
1009   }
1010 
1011   // Variant that takes explicit vector of addresss
1012   // (to test restricted addressing modes set).
RepeatA(void (Ass::* f)(const Addr &),const std::vector<Addr> & a,const std::string & fmt)1013   std::string RepeatA(void (Ass::*f)(const Addr&),
1014                       const std::vector<Addr>& a,
1015                       const std::string& fmt) {
1016     return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
1017   }
1018 
1019   // Repeats over addresses and immediates provided by fixture.
RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::string & fmt)1020   std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
1021                        size_t imm_bytes,
1022                        const std::string& fmt) {
1023     return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
1024   }
1025 
1026   // Variant that takes explicit vector of addresss
1027   // (to test restricted addressing modes set).
RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::vector<Addr> & a,const std::string & fmt)1028   std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
1029                        size_t imm_bytes,
1030                        const std::vector<Addr>& a,
1031                        const std::string& fmt) {
1032     return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
1033   }
1034 
1035   // Repeats over registers and addresses provided by fixture.
RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1036   std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1037     return RepeatRA(f, GetAddresses(), fmt);
1038   }
1039 
1040   // Variant that takes explicit vector of addresss
1041   // (to test restricted addressing modes set).
RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1042   std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
1043                        const std::vector<Addr>& a,
1044                        const std::string& fmt) {
1045     return RepeatTemplatedRegMem<Reg, Addr>(
1046         f,
1047         GetRegisters(),
1048         a,
1049         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1050         &AssemblerTest::GetAddrName,
1051         fmt);
1052   }
1053 
1054   // Repeats over secondary registers and addresses provided by fixture.
RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1055   std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1056     return RepeatrA(f, GetAddresses(), fmt);
1057   }
1058 
1059   // Variant that takes explicit vector of addresss
1060   // (to test restricted addressing modes set).
RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1061   std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
1062                        const std::vector<Addr>& a,
1063                        const std::string& fmt) {
1064     return RepeatTemplatedRegMem<Reg, Addr>(
1065         f,
1066         GetRegisters(),
1067         a,
1068         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1069         &AssemblerTest::GetAddrName,
1070         fmt);
1071   }
1072 
1073   // Repeats over tertiary registers and addresses provided by fixture.
RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1074   std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1075     return RepeatwA(f, GetAddresses(), fmt);
1076   }
1077 
1078   // Variant that takes explicit vector of addresss
1079   // (to test restricted addressing modes set).
RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1080   std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
1081                        const std::vector<Addr>& a,
1082                        const std::string& fmt) {
1083     return RepeatTemplatedRegMem<Reg, Addr>(
1084         f,
1085         GetRegisters(),
1086         a,
1087         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1088         &AssemblerTest::GetAddrName,
1089         fmt);
1090   }
1091 
1092   // Repeats over quaternary registers and addresses provided by fixture.
RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1093   std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1094     return RepeatbA(f, GetAddresses(), fmt);
1095   }
1096 
1097   // Variant that takes explicit vector of addresss
1098   // (to test restricted addressing modes set).
RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1099   std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
1100                        const std::vector<Addr>& a,
1101                        const std::string& fmt) {
1102     return RepeatTemplatedRegMem<Reg, Addr>(
1103         f,
1104         GetRegisters(),
1105         a,
1106         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1107         &AssemblerTest::GetAddrName,
1108         fmt);
1109   }
1110 
1111   // Repeats over fp-registers and addresses provided by fixture.
RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::string & fmt)1112   std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
1113     return RepeatFA(f, GetAddresses(), fmt);
1114   }
1115 
1116   // Variant that takes explicit vector of addresss
1117   // (to test restricted addressing modes set).
RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1118   std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1119                        const std::vector<Addr>& a,
1120                        const std::string& fmt) {
1121     return RepeatTemplatedRegMem<FPReg, Addr>(
1122         f,
1123         GetFPRegisters(),
1124         a,
1125         &AssemblerTest::GetFPRegName,
1126         &AssemblerTest::GetAddrName,
1127         fmt);
1128   }
1129 
1130   // Repeats over addresses and registers provided by fixture.
RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1131   std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1132     return RepeatAR(f, GetAddresses(), fmt);
1133   }
1134 
1135   // Variant that takes explicit vector of addresss
1136   // (to test restricted addressing modes set).
RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1137   std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1138                        const std::vector<Addr>& a,
1139                        const std::string& fmt) {
1140     return RepeatTemplatedMemReg<Addr, Reg>(
1141         f,
1142         a,
1143         GetRegisters(),
1144         &AssemblerTest::GetAddrName,
1145         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1146         fmt);
1147   }
1148 
1149   // Repeats over addresses and secondary registers provided by fixture.
RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1150   std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1151     return RepeatAr(f, GetAddresses(), fmt);
1152   }
1153 
1154   // Variant that takes explicit vector of addresss
1155   // (to test restricted addressing modes set).
RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1156   std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1157                        const std::vector<Addr>& a,
1158                        const std::string& fmt) {
1159     return RepeatTemplatedMemReg<Addr, Reg>(
1160         f,
1161         a,
1162         GetRegisters(),
1163         &AssemblerTest::GetAddrName,
1164         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1165         fmt);
1166   }
1167 
1168   // Repeats over addresses and tertiary registers provided by fixture.
RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1169   std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1170     return RepeatAw(f, GetAddresses(), fmt);
1171   }
1172 
1173   // Variant that takes explicit vector of addresss
1174   // (to test restricted addressing modes set).
RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1175   std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1176                        const std::vector<Addr>& a,
1177                        const std::string& fmt) {
1178     return RepeatTemplatedMemReg<Addr, Reg>(
1179         f,
1180         a,
1181         GetRegisters(),
1182         &AssemblerTest::GetAddrName,
1183         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1184         fmt);
1185   }
1186 
1187   // Repeats over addresses and quaternary registers provided by fixture.
RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1188   std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1189     return RepeatAb(f, GetAddresses(), fmt);
1190   }
1191 
1192   // Variant that takes explicit vector of addresss
1193   // (to test restricted addressing modes set).
RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1194   std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1195                        const std::vector<Addr>& a,
1196                        const std::string& fmt) {
1197     return RepeatTemplatedMemReg<Addr, Reg>(
1198         f,
1199         a,
1200         GetRegisters(),
1201         &AssemblerTest::GetAddrName,
1202         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1203         fmt);
1204   }
1205 
1206   // Repeats over addresses and fp-registers provided by fixture.
RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::string & fmt)1207   std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1208     return RepeatAF(f, GetAddresses(), fmt);
1209   }
1210 
1211   // Variant that takes explicit vector of addresss
1212   // (to test restricted addressing modes set).
RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::vector<Addr> & a,const std::string & fmt)1213   std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1214                        const std::vector<Addr>& a,
1215                        const std::string& fmt) {
1216     return RepeatTemplatedMemReg<Addr, FPReg>(
1217         f,
1218         a,
1219         GetFPRegisters(),
1220         &AssemblerTest::GetAddrName,
1221         &AssemblerTest::GetFPRegName,
1222         fmt);
1223   }
1224 
1225   template <typename AddrType>
RepeatTemplatedMem(void (Ass::* f)(const AddrType &),const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1226   std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1227                                  const std::vector<AddrType> addresses,
1228                                  std::string (AssemblerTest::*GetAName)(const AddrType&),
1229                                  const std::string& fmt) {
1230     WarnOnCombinations(addresses.size());
1231     std::string str;
1232     for (auto addr : addresses) {
1233       if (f != nullptr) {
1234         (assembler_.get()->*f)(addr);
1235       }
1236       std::string base = fmt;
1237 
1238       ReplaceAddr((this->*GetAName)(addr), &base);
1239 
1240       str += base;
1241       str += "\n";
1242     }
1243     return str;
1244   }
1245 
1246   template <typename AddrType>
RepeatTemplatedMemImm(void (Ass::* f)(const AddrType &,const Imm &),size_t imm_bytes,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1247   std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1248                                     size_t imm_bytes,
1249                                     const std::vector<AddrType> addresses,
1250                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1251                                     const std::string& fmt) {
1252     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1253     WarnOnCombinations(addresses.size() * imms.size());
1254     std::string str;
1255     for (auto addr : addresses) {
1256       for (int64_t imm : imms) {
1257         Imm new_imm = CreateImmediate(imm);
1258         if (f != nullptr) {
1259           (assembler_.get()->*f)(addr, new_imm);
1260         }
1261         std::string base = fmt;
1262 
1263         ReplaceAddr((this->*GetAName)(addr), &base);
1264         ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
1265 
1266         str += base;
1267         str += "\n";
1268       }
1269     }
1270     return str;
1271   }
1272 
1273   template <typename RegType, typename AddrType>
RepeatTemplatedRegMem(void (Ass::* f)(RegType,const AddrType &),ArrayRef<const RegType> registers,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetRName)(const RegType &),std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1274   std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1275                                     ArrayRef<const RegType> registers,
1276                                     const std::vector<AddrType> addresses,
1277                                     std::string (AssemblerTest::*GetRName)(const RegType&),
1278                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1279                                     const std::string& fmt) {
1280     WarnOnCombinations(addresses.size() * registers.size());
1281     std::string str;
1282     for (auto reg : registers) {
1283       for (auto addr : addresses) {
1284         if (f != nullptr) {
1285           (assembler_.get()->*f)(reg, addr);
1286         }
1287         std::string base = fmt;
1288 
1289         ReplaceReg(REG_TOKEN, (this->*GetRName)(reg), &base);
1290         ReplaceAddr((this->*GetAName)(addr), &base);
1291 
1292         str += base;
1293         str += "\n";
1294       }
1295     }
1296     return str;
1297   }
1298 
1299   template <typename AddrType, typename RegType>
RepeatTemplatedMemReg(void (Ass::* f)(const AddrType &,RegType),const std::vector<AddrType> addresses,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetAName)(const AddrType &),std::string (AssemblerTest::* GetRName)(const RegType &),const std::string & fmt)1300   std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1301                                     const std::vector<AddrType> addresses,
1302                                     ArrayRef<const RegType> registers,
1303                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1304                                     std::string (AssemblerTest::*GetRName)(const RegType&),
1305                                     const std::string& fmt) {
1306     WarnOnCombinations(addresses.size() * registers.size());
1307     std::string str;
1308     for (auto addr : addresses) {
1309       for (auto reg : registers) {
1310         if (f != nullptr) {
1311           (assembler_.get()->*f)(addr, reg);
1312         }
1313         std::string base = fmt;
1314 
1315         ReplaceAddr((this->*GetAName)(addr), &base);
1316         ReplaceReg(REG_TOKEN, (this->*GetRName)(reg), &base);
1317 
1318         str += base;
1319         str += "\n";
1320       }
1321     }
1322     return str;
1323   }
1324 
1325   //
1326   // Register repeats.
1327   //
1328 
1329   template <typename RegType>
RepeatTemplatedRegister(void (Ass::* f)(RegType),ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt)1330   std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1331                                       ArrayRef<const RegType> registers,
1332                                       std::string (AssemblerTest::*GetName)(const RegType&),
1333                                       const std::string& fmt) {
1334     std::string str;
1335     for (auto reg : registers) {
1336       if (f != nullptr) {
1337         (assembler_.get()->*f)(reg);
1338       }
1339       std::string base = fmt;
1340 
1341       ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base);
1342 
1343       str += base;
1344       str += "\n";
1345     }
1346     return str;
1347   }
1348 
1349   template <typename Reg1, typename Reg2>
1350   std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1351                                        ArrayRef<const Reg1> reg1_registers,
1352                                        ArrayRef<const Reg2> reg2_registers,
1353                                        std::string (AssemblerTest::*GetName1)(const Reg1&),
1354                                        std::string (AssemblerTest::*GetName2)(const Reg2&),
1355                                        const std::string& fmt,
1356                                        const std::vector<std::pair<Reg1, Reg2>>* except = nullptr) {
1357     WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1358 
1359     std::string str;
1360     for (auto reg1 : reg1_registers) {
1361       for (auto reg2 : reg2_registers) {
1362         // Check if this register pair is on the exception list. If so, skip it.
1363         if (except != nullptr) {
1364           const auto& pair = std::make_pair(reg1, reg2);
1365           if (std::find(except->begin(), except->end(), pair) != except->end()) {
1366             continue;
1367           }
1368         }
1369 
1370         if (f != nullptr) {
1371           (assembler_.get()->*f)(reg1, reg2);
1372         }
1373         std::string base = fmt;
1374 
1375         ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
1376         ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
1377 
1378         str += base;
1379         str += "\n";
1380       }
1381     }
1382     return str;
1383   }
1384 
1385   template <typename Reg1, typename Reg2>
RepeatTemplatedRegistersNoDupes(void (Ass::* f)(Reg1,Reg2),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),const std::string & fmt)1386   std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1387                                               ArrayRef<const Reg1> reg1_registers,
1388                                               ArrayRef<const Reg2> reg2_registers,
1389                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
1390                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
1391                                               const std::string& fmt) {
1392     WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1393 
1394     std::string str;
1395     for (auto reg1 : reg1_registers) {
1396       for (auto reg2 : reg2_registers) {
1397         if (reg1 == reg2) continue;
1398         if (f != nullptr) {
1399           (assembler_.get()->*f)(reg1, reg2);
1400         }
1401         std::string base = fmt;
1402 
1403         ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
1404         ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
1405 
1406         str += base;
1407         str += "\n";
1408       }
1409     }
1410     return str;
1411   }
1412 
1413   template <typename Reg1, typename Reg2, typename Reg3>
RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2,Reg3),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),const std::string & fmt)1414   std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1415                                        ArrayRef<const Reg1> reg1_registers,
1416                                        ArrayRef<const Reg2> reg2_registers,
1417                                        ArrayRef<const Reg3> reg3_registers,
1418                                        std::string (AssemblerTest::*GetName1)(const Reg1&),
1419                                        std::string (AssemblerTest::*GetName2)(const Reg2&),
1420                                        std::string (AssemblerTest::*GetName3)(const Reg3&),
1421                                        const std::string& fmt) {
1422     std::string str;
1423     for (auto reg1 : reg1_registers) {
1424       for (auto reg2 : reg2_registers) {
1425         for (auto reg3 : reg3_registers) {
1426           if (f != nullptr) {
1427             (assembler_.get()->*f)(reg1, reg2, reg3);
1428           }
1429           std::string base = fmt;
1430 
1431           ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
1432           ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
1433           ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base);
1434 
1435           str += base;
1436           str += "\n";
1437         }
1438       }
1439     }
1440     return str;
1441   }
1442 
1443   template <typename Reg1, typename Reg2, typename Reg3, typename Reg4>
RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2,Reg3,Reg4),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,ArrayRef<const Reg4> reg4_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),std::string (AssemblerTest::* GetName4)(const Reg4 &),const std::string & fmt)1444   std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3, Reg4),
1445                                        ArrayRef<const Reg1> reg1_registers,
1446                                        ArrayRef<const Reg2> reg2_registers,
1447                                        ArrayRef<const Reg3> reg3_registers,
1448                                        ArrayRef<const Reg4> reg4_registers,
1449                                        std::string (AssemblerTest::*GetName1)(const Reg1&),
1450                                        std::string (AssemblerTest::*GetName2)(const Reg2&),
1451                                        std::string (AssemblerTest::*GetName3)(const Reg3&),
1452                                        std::string (AssemblerTest::*GetName4)(const Reg4&),
1453                                        const std::string& fmt) {
1454     std::string str;
1455     for (auto reg1 : reg1_registers) {
1456       for (auto reg2 : reg2_registers) {
1457         for (auto reg3 : reg3_registers) {
1458           for (auto reg4 : reg4_registers) {
1459             if (f != nullptr) {
1460               (assembler_.get()->*f)(reg1, reg2, reg3, reg4);
1461             }
1462             std::string base = fmt;
1463 
1464             ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
1465             ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
1466             ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base);
1467             ReplaceReg(REG4_TOKEN, (this->*GetName4)(reg4), &base);
1468 
1469             str += base;
1470             str += "\n";
1471           }
1472         }
1473       }
1474     }
1475     return str;
1476   }
1477 
1478   template <typename Reg1, typename Reg2>
RepeatTemplatedRegistersImm(void (Ass::* f)(Reg1,Reg2,const Imm &),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),size_t imm_bytes,const std::string & fmt)1479   std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1480                                           ArrayRef<const Reg1> reg1_registers,
1481                                           ArrayRef<const Reg2> reg2_registers,
1482                                           std::string (AssemblerTest::*GetName1)(const Reg1&),
1483                                           std::string (AssemblerTest::*GetName2)(const Reg2&),
1484                                           size_t imm_bytes,
1485                                           const std::string& fmt) {
1486     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1487     WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1488 
1489     std::string str;
1490     for (auto reg1 : reg1_registers) {
1491       for (auto reg2 : reg2_registers) {
1492         for (int64_t imm : imms) {
1493           Imm new_imm = CreateImmediate(imm);
1494           if (f != nullptr) {
1495             (assembler_.get()->*f)(reg1, reg2, new_imm);
1496           }
1497           std::string base = fmt;
1498 
1499           ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base);
1500           ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base);
1501           ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
1502 
1503           str += base;
1504           str += "\n";
1505         }
1506       }
1507     }
1508     return str;
1509   }
1510 
GetAddrName(const Addr & addr)1511   std::string GetAddrName(const Addr& addr) {
1512     std::ostringstream saddr;
1513     saddr << addr;
1514     return saddr.str();
1515   }
1516 
1517   template <RegisterView kRegView>
GetRegName(const Reg & reg)1518   std::string GetRegName(const Reg& reg) {
1519     std::ostringstream sreg;
1520     switch (kRegView) {
1521       case RegisterView::kUsePrimaryName:
1522         sreg << reg;
1523         break;
1524 
1525       case RegisterView::kUseSecondaryName:
1526         sreg << GetSecondaryRegisterName(reg);
1527         break;
1528 
1529       case RegisterView::kUseTertiaryName:
1530         sreg << GetTertiaryRegisterName(reg);
1531         break;
1532 
1533       case RegisterView::kUseQuaternaryName:
1534         sreg << GetQuaternaryRegisterName(reg);
1535         break;
1536     }
1537     return sreg.str();
1538   }
1539 
GetFPRegName(const FPReg & reg)1540   std::string GetFPRegName(const FPReg& reg) {
1541     std::ostringstream sreg;
1542     sreg << reg;
1543     return sreg.str();
1544   }
1545 
GetVecRegName(const VecReg & reg)1546   std::string GetVecRegName(const VecReg& reg) {
1547     std::ostringstream sreg;
1548     sreg << reg;
1549     return sreg.str();
1550   }
1551 
WarnOnCombinations(size_t count)1552   void WarnOnCombinations(size_t count) {
1553     if (count > kWarnManyCombinationsThreshold) {
1554       GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1555     }
1556   }
1557 
ReplaceReg(const std::string & reg_token,const std::string & replacement,std::string * str)1558   static void ReplaceReg(const std::string& reg_token,
1559                          const std::string& replacement,
1560                          /*inout*/ std::string* str) {
1561     size_t reg_index;
1562     while ((reg_index = str->find(reg_token)) != std::string::npos) {
1563       str->replace(reg_index, reg_token.length(), replacement);
1564     }
1565   }
1566 
ReplaceImm(int64_t imm,int64_t bias,int64_t multiplier,std::string * str)1567   static void ReplaceImm(int64_t imm,
1568                          int64_t bias,
1569                          int64_t multiplier,
1570                          /*inout*/ std::string* str) {
1571     size_t imm_index = str->find(IMM_TOKEN);
1572     if (imm_index != std::string::npos) {
1573       std::ostringstream sreg;
1574       sreg << imm * multiplier + bias;
1575       std::string imm_string = sreg.str();
1576       str->replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1577     }
1578   }
1579 
ReplaceAddr(const std::string & replacement,std::string * str)1580   static void ReplaceAddr(const std::string& replacement, /*inout*/ std::string* str) {
1581     size_t addr_index;
1582     if ((addr_index = str->find(ADDRESS_TOKEN)) != std::string::npos) {
1583       str->replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), replacement);
1584     }
1585   }
1586 
1587   static constexpr const char* ADDRESS_TOKEN = "{mem}";
1588   static constexpr const char* REG_TOKEN = "{reg}";
1589   static constexpr const char* REG1_TOKEN = "{reg1}";
1590   static constexpr const char* REG2_TOKEN = "{reg2}";
1591   static constexpr const char* REG3_TOKEN = "{reg3}";
1592   static constexpr const char* REG4_TOKEN = "{reg4}";
1593   static constexpr const char* IMM_TOKEN = "{imm}";
1594 
1595  private:
1596   template <RegisterView kRegView>
RepeatRegisterImm(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)1597   std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1598                                 size_t imm_bytes,
1599                                 const std::string& fmt) {
1600     ArrayRef<const Reg> registers = GetRegisters();
1601     std::string str;
1602     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1603 
1604     WarnOnCombinations(registers.size() * imms.size());
1605 
1606     for (auto reg : registers) {
1607       for (int64_t imm : imms) {
1608         Imm new_imm = CreateImmediate(imm);
1609         if (f != nullptr) {
1610           (assembler_.get()->*f)(reg, new_imm);
1611         }
1612         std::string base = fmt;
1613 
1614         ReplaceReg(REG_TOKEN, GetRegName<kRegView>(reg), &base);
1615         ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
1616 
1617         str += base;
1618         str += "\n";
1619       }
1620     }
1621     return str;
1622   }
1623 
1624   // Override this to pad the code with NOPs to a certain size if needed.
Pad(std::vector<uint8_t> & data)1625   virtual void Pad([[maybe_unused]] std::vector<uint8_t>& data) {}
1626 
DriverWrapper(const std::string & assembly_text,const std::string & test_name)1627   void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
1628     assembler_->FinalizeCode();
1629     size_t cs = assembler_->CodeSize();
1630     std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
1631     MemoryRegion code(&(*data)[0], data->size());
1632     assembler_->CopyInstructions(code);
1633     Pad(*data);
1634     Driver(*data, assembly_text, test_name);
1635   }
1636 
1637   static constexpr size_t kWarnManyCombinationsThreshold = 500;
1638 
1639   MallocArenaPool pool_;
1640   std::unique_ptr<ArenaAllocator> allocator_;
1641   std::unique_ptr<Ass> assembler_;
1642 
1643   DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
1644 };
1645 
1646 }  // namespace art
1647 
1648 #endif  // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
1649