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