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_ARM_ASSEMBLER_ARM_TEST_H_
18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
19 
20 #include "utils/assembler_test.h"
21 
22 namespace art {
23 
24 template<typename Ass, typename Reg, typename FPReg, typename Imm, typename SOp, typename Cond>
25 class AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> {
26  public:
27   typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base;
28 
29   using Base::GetRegisters;
30   using Base::GetRegName;
31   using Base::CreateImmediate;
32   using Base::WarnOnCombinations;
33 
34   static constexpr int64_t kFullImmRangeThreshold = 32;
35 
FillImmediates(std::vector<Imm> & immediates,int64_t imm_min,int64_t imm_max)36   virtual void FillImmediates(std::vector<Imm>& immediates, int64_t imm_min, int64_t imm_max) {
37     // Small range: do completely.
38     if (imm_max - imm_min <= kFullImmRangeThreshold) {
39       for (int64_t i = imm_min; i <= imm_max; ++i) {
40         immediates.push_back(CreateImmediate(i));
41       }
42     } else {
43       immediates.push_back(CreateImmediate(imm_min));
44       immediates.push_back(CreateImmediate(imm_max));
45       if (imm_min < imm_max - 1) {
46         immediates.push_back(CreateImmediate(imm_min + 1));
47       }
48       if (imm_min < imm_max - 2) {
49         immediates.push_back(CreateImmediate(imm_min + 2));
50       }
51       if (imm_min < imm_max - 3) {
52         immediates.push_back(CreateImmediate(imm_max - 1));
53       }
54       if (imm_min < imm_max - 4) {
55         immediates.push_back(CreateImmediate((imm_min + imm_max) / 2));
56       }
57     }
58   }
59 
RepeatRRIIC(void (Ass::* f)(Reg,Reg,Imm,Imm,Cond),int64_t imm1_min,int64_t imm1_max,int64_t imm2_min,int64_t imm2_max,std::string fmt)60   std::string RepeatRRIIC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
61                           int64_t imm1_min, int64_t imm1_max,
62                           int64_t imm2_min, int64_t imm2_max,
63                           std::string fmt) {
64     return RepeatTemplatedRRIIC(f, GetRegisters(), GetRegisters(),
65                                 &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
66                                 &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
67                                 imm1_min, imm1_max, imm2_min, imm2_max,
68                                 fmt);
69   }
70 
71   template <typename Reg1, typename Reg2>
RepeatTemplatedRRIIC(void (Ass::* f)(Reg1,Reg2,Imm,Imm,Cond),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerArmTest::* GetName1)(const Reg1 &),std::string (AssemblerArmTest::* GetName2)(const Reg2 &),int64_t imm1_min,int64_t imm1_max,int64_t imm2_min,int64_t imm2_max,std::string fmt)72   std::string RepeatTemplatedRRIIC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
73                                    const std::vector<Reg1*> reg1_registers,
74                                    const std::vector<Reg2*> reg2_registers,
75                                    std::string (AssemblerArmTest::*GetName1)(const Reg1&),
76                                    std::string (AssemblerArmTest::*GetName2)(const Reg2&),
77                                    int64_t imm1_min, int64_t imm1_max,
78                                    int64_t imm2_min, int64_t imm2_max,
79                                    std::string fmt) {
80     std::vector<Imm> immediates1;
81     FillImmediates(immediates1, imm1_min, imm1_max);
82     std::vector<Imm> immediates2;
83     FillImmediates(immediates2, imm2_min, imm2_max);
84 
85     std::vector<Cond>& cond = GetConditions();
86 
87     WarnOnCombinations(cond.size() * immediates1.size() * immediates2.size() *
88                        reg1_registers.size() * reg2_registers.size());
89 
90     std::ostringstream oss;
91     bool first = true;
92     for (Cond& c : cond) {
93       std::string after_cond = fmt;
94 
95       size_t cond_index = after_cond.find(COND_TOKEN);
96       if (cond_index != std::string::npos) {
97         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
98       }
99 
100       for (Imm i : immediates1) {
101         std::string base = after_cond;
102 
103         size_t imm1_index = base.find(IMM1_TOKEN);
104         if (imm1_index != std::string::npos) {
105           std::ostringstream sreg;
106           sreg << i;
107           std::string imm_string = sreg.str();
108           base.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
109         }
110 
111         for (Imm j : immediates2) {
112           std::string base2 = base;
113 
114           size_t imm2_index = base2.find(IMM2_TOKEN);
115           if (imm2_index != std::string::npos) {
116             std::ostringstream sreg;
117             sreg << j;
118             std::string imm_string = sreg.str();
119             base2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
120           }
121 
122           for (auto reg1 : reg1_registers) {
123             std::string base3 = base2;
124 
125             std::string reg1_string = (this->*GetName1)(*reg1);
126             size_t reg1_index;
127             while ((reg1_index = base3.find(Base::REG1_TOKEN)) != std::string::npos) {
128               base3.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
129             }
130 
131             for (auto reg2 : reg2_registers) {
132               std::string base4 = base3;
133 
134               std::string reg2_string = (this->*GetName2)(*reg2);
135               size_t reg2_index;
136               while ((reg2_index = base4.find(Base::REG2_TOKEN)) != std::string::npos) {
137                 base4.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
138               }
139 
140               if (first) {
141                 first = false;
142               } else {
143                 oss << "\n";
144               }
145               oss << base4;
146 
147               (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
148             }
149           }
150         }
151       }
152     }
153     // Add a newline at the end.
154     oss << "\n";
155 
156     return oss.str();
157   }
158 
RepeatRRiiC(void (Ass::* f)(Reg,Reg,Imm,Imm,Cond),std::vector<std::pair<Imm,Imm>> & immediates,std::string fmt)159   std::string RepeatRRiiC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
160                           std::vector<std::pair<Imm, Imm>>& immediates,
161                           std::string fmt) {
162     return RepeatTemplatedRRiiC<Reg, Reg>(f, GetRegisters(), GetRegisters(),
163         &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
164         &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
165         immediates, fmt);
166   }
167 
168   template <typename Reg1, typename Reg2>
RepeatTemplatedRRiiC(void (Ass::* f)(Reg1,Reg2,Imm,Imm,Cond),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerArmTest::* GetName1)(const Reg1 &),std::string (AssemblerArmTest::* GetName2)(const Reg2 &),std::vector<std::pair<Imm,Imm>> & immediates,std::string fmt)169   std::string RepeatTemplatedRRiiC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
170         const std::vector<Reg1*> reg1_registers,
171         const std::vector<Reg2*> reg2_registers,
172         std::string (AssemblerArmTest::*GetName1)(const Reg1&),
173         std::string (AssemblerArmTest::*GetName2)(const Reg2&),
174         std::vector<std::pair<Imm, Imm>>& immediates,
175         std::string fmt) {
176     std::vector<Cond>& cond = GetConditions();
177 
178     WarnOnCombinations(cond.size() * immediates.size() * reg1_registers.size() *
179                        reg2_registers.size());
180 
181     std::ostringstream oss;
182     bool first = true;
183     for (Cond& c : cond) {
184       std::string after_cond = fmt;
185 
186       size_t cond_index = after_cond.find(COND_TOKEN);
187       if (cond_index != std::string::npos) {
188         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
189       }
190 
191       for (std::pair<Imm, Imm>& pair : immediates) {
192         Imm i = pair.first;
193         Imm j = pair.second;
194         std::string after_imm1 = after_cond;
195 
196         size_t imm1_index = after_imm1.find(IMM1_TOKEN);
197         if (imm1_index != std::string::npos) {
198           std::ostringstream sreg;
199           sreg << i;
200           std::string imm_string = sreg.str();
201           after_imm1.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
202         }
203 
204         std::string after_imm2 = after_imm1;
205 
206         size_t imm2_index = after_imm2.find(IMM2_TOKEN);
207         if (imm2_index != std::string::npos) {
208           std::ostringstream sreg;
209           sreg << j;
210           std::string imm_string = sreg.str();
211           after_imm2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
212         }
213 
214         for (auto reg1 : reg1_registers) {
215           std::string after_reg1 = after_imm2;
216 
217           std::string reg1_string = (this->*GetName1)(*reg1);
218           size_t reg1_index;
219           while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
220             after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
221           }
222 
223           for (auto reg2 : reg2_registers) {
224             std::string after_reg2 = after_reg1;
225 
226             std::string reg2_string = (this->*GetName2)(*reg2);
227             size_t reg2_index;
228             while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
229               after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
230             }
231 
232             if (first) {
233               first = false;
234             } else {
235               oss << "\n";
236             }
237             oss << after_reg2;
238 
239             (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
240           }
241         }
242       }
243     }
244     // Add a newline at the end.
245     oss << "\n";
246 
247     return oss.str();
248   }
249 
RepeatRRC(void (Ass::* f)(Reg,Reg,Cond),std::string fmt)250   std::string RepeatRRC(void (Ass::*f)(Reg, Reg, Cond), std::string fmt) {
251     return RepeatTemplatedRRC(f, GetRegisters(), GetRegisters(), GetConditions(),
252         &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
253         &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
254         fmt);
255   }
256 
257   template <typename Reg1, typename Reg2>
RepeatTemplatedRRC(void (Ass::* f)(Reg1,Reg2,Cond),const std::vector<Reg1 * > & reg1_registers,const std::vector<Reg2 * > & reg2_registers,const std::vector<Cond> & cond,std::string (AssemblerArmTest::* GetName1)(const Reg1 &),std::string (AssemblerArmTest::* GetName2)(const Reg2 &),std::string fmt)258   std::string RepeatTemplatedRRC(void (Ass::*f)(Reg1, Reg2, Cond),
259                                  const std::vector<Reg1*>& reg1_registers,
260                                  const std::vector<Reg2*>& reg2_registers,
261                                  const std::vector<Cond>& cond,
262                                  std::string (AssemblerArmTest::*GetName1)(const Reg1&),
263                                  std::string (AssemblerArmTest::*GetName2)(const Reg2&),
264                                  std::string fmt) {
265     WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size());
266 
267     std::ostringstream oss;
268     bool first = true;
269     for (const Cond& c : cond) {
270       std::string after_cond = fmt;
271 
272       size_t cond_index = after_cond.find(COND_TOKEN);
273       if (cond_index != std::string::npos) {
274         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
275       }
276 
277       for (auto reg1 : reg1_registers) {
278         std::string after_reg1 = after_cond;
279 
280         std::string reg1_string = (this->*GetName1)(*reg1);
281         size_t reg1_index;
282         while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
283           after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
284         }
285 
286         for (auto reg2 : reg2_registers) {
287           std::string after_reg2 = after_reg1;
288 
289           std::string reg2_string = (this->*GetName2)(*reg2);
290           size_t reg2_index;
291           while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
292             after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
293           }
294 
295           if (first) {
296             first = false;
297           } else {
298             oss << "\n";
299           }
300           oss << after_reg2;
301 
302           (Base::GetAssembler()->*f)(*reg1, *reg2, c);
303         }
304       }
305     }
306     // Add a newline at the end.
307     oss << "\n";
308 
309     return oss.str();
310   }
311 
RepeatRRRC(void (Ass::* f)(Reg,Reg,Reg,Cond),std::string fmt)312   std::string RepeatRRRC(void (Ass::*f)(Reg, Reg, Reg, Cond), std::string fmt) {
313     return RepeatTemplatedRRRC(f, GetRegisters(), GetRegisters(), GetRegisters(), GetConditions(),
314                                &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
315                                &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
316                                &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
317                                fmt);
318   }
319 
320   template <typename Reg1, typename Reg2, typename Reg3>
RepeatTemplatedRRRC(void (Ass::* f)(Reg1,Reg2,Reg3,Cond),const std::vector<Reg1 * > & reg1_registers,const std::vector<Reg2 * > & reg2_registers,const std::vector<Reg3 * > & reg3_registers,const std::vector<Cond> & cond,std::string (AssemblerArmTest::* GetName1)(const Reg1 &),std::string (AssemblerArmTest::* GetName2)(const Reg2 &),std::string (AssemblerArmTest::* GetName3)(const Reg3 &),std::string fmt)321   std::string RepeatTemplatedRRRC(void (Ass::*f)(Reg1, Reg2, Reg3, Cond),
322                                   const std::vector<Reg1*>& reg1_registers,
323                                   const std::vector<Reg2*>& reg2_registers,
324                                   const std::vector<Reg3*>& reg3_registers,
325                                   const std::vector<Cond>& cond,
326                                   std::string (AssemblerArmTest::*GetName1)(const Reg1&),
327                                   std::string (AssemblerArmTest::*GetName2)(const Reg2&),
328                                   std::string (AssemblerArmTest::*GetName3)(const Reg3&),
329                                   std::string fmt) {
330     WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() *
331                        reg3_registers.size());
332 
333     std::ostringstream oss;
334     bool first = true;
335     for (const Cond& c : cond) {
336       std::string after_cond = fmt;
337 
338       size_t cond_index = after_cond.find(COND_TOKEN);
339       if (cond_index != std::string::npos) {
340         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
341       }
342 
343       for (auto reg1 : reg1_registers) {
344         std::string after_reg1 = after_cond;
345 
346         std::string reg1_string = (this->*GetName1)(*reg1);
347         size_t reg1_index;
348         while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
349           after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
350         }
351 
352         for (auto reg2 : reg2_registers) {
353           std::string after_reg2 = after_reg1;
354 
355           std::string reg2_string = (this->*GetName2)(*reg2);
356           size_t reg2_index;
357           while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
358             after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
359           }
360 
361           for (auto reg3 : reg3_registers) {
362             std::string after_reg3 = after_reg2;
363 
364             std::string reg3_string = (this->*GetName3)(*reg3);
365             size_t reg3_index;
366             while ((reg3_index = after_reg3.find(REG3_TOKEN)) != std::string::npos) {
367               after_reg3.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
368             }
369 
370             if (first) {
371               first = false;
372             } else {
373               oss << "\n";
374             }
375             oss << after_reg3;
376 
377             (Base::GetAssembler()->*f)(*reg1, *reg2, *reg3, c);
378           }
379         }
380       }
381     }
382     // Add a newline at the end.
383     oss << "\n";
384 
385     return oss.str();
386   }
387 
388   template <typename RegT>
RepeatTemplatedRSC(void (Ass::* f)(RegT,SOp,Cond),const std::vector<RegT * > & registers,const std::vector<SOp> & shifts,const std::vector<Cond> & cond,std::string (AssemblerArmTest::* GetName)(const RegT &),std::string fmt)389   std::string RepeatTemplatedRSC(void (Ass::*f)(RegT, SOp, Cond),
390                                  const std::vector<RegT*>& registers,
391                                  const std::vector<SOp>& shifts,
392                                  const std::vector<Cond>& cond,
393                                  std::string (AssemblerArmTest::*GetName)(const RegT&),
394                                  std::string fmt) {
395     WarnOnCombinations(cond.size() * registers.size() * shifts.size());
396 
397     std::ostringstream oss;
398     bool first = true;
399     for (const Cond& c : cond) {
400       std::string after_cond = fmt;
401 
402       size_t cond_index = after_cond.find(COND_TOKEN);
403       if (cond_index != std::string::npos) {
404         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
405       }
406 
407       for (const SOp& shift : shifts) {
408         std::string after_shift = after_cond;
409 
410         std::string shift_string = GetShiftString(shift);
411         size_t shift_index;
412         while ((shift_index = after_shift.find(Base::SHIFT_TOKEN)) != std::string::npos) {
413           after_shift.replace(shift_index, ConstexprStrLen(Base::SHIFT_TOKEN), shift_string);
414         }
415 
416         for (auto reg : registers) {
417           std::string after_reg = after_shift;
418 
419           std::string reg_string = (this->*GetName)(*reg);
420           size_t reg_index;
421           while ((reg_index = after_reg.find(Base::REG_TOKEN)) != std::string::npos) {
422             after_reg.replace(reg_index, ConstexprStrLen(Base::REG_TOKEN), reg_string);
423           }
424 
425           if (first) {
426             first = false;
427           } else {
428             oss << "\n";
429           }
430           oss << after_reg;
431 
432           (Base::GetAssembler()->*f)(*reg, shift, c);
433         }
434       }
435     }
436     // Add a newline at the end.
437     oss << "\n";
438 
439     return oss.str();
440   }
441 
442   template <typename Reg1, typename Reg2>
RepeatTemplatedRRSC(void (Ass::* f)(Reg1,Reg2,const SOp &,Cond),const std::vector<Reg1 * > & reg1_registers,const std::vector<Reg2 * > & reg2_registers,const std::vector<SOp> & shifts,const std::vector<Cond> & cond,std::string (AssemblerArmTest::* GetName1)(const Reg1 &),std::string (AssemblerArmTest::* GetName2)(const Reg2 &),std::string fmt)443   std::string RepeatTemplatedRRSC(void (Ass::*f)(Reg1, Reg2, const SOp&, Cond),
444                                   const std::vector<Reg1*>& reg1_registers,
445                                   const std::vector<Reg2*>& reg2_registers,
446                                   const std::vector<SOp>& shifts,
447                                   const std::vector<Cond>& cond,
448                                   std::string (AssemblerArmTest::*GetName1)(const Reg1&),
449                                   std::string (AssemblerArmTest::*GetName2)(const Reg2&),
450                                   std::string fmt) {
451     WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() * shifts.size());
452 
453     std::ostringstream oss;
454     bool first = true;
455     for (const Cond& c : cond) {
456       std::string after_cond = fmt;
457 
458       size_t cond_index = after_cond.find(COND_TOKEN);
459       if (cond_index != std::string::npos) {
460         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
461       }
462 
463       for (const SOp& shift : shifts) {
464         std::string after_shift = after_cond;
465 
466         std::string shift_string = GetShiftString(shift);
467         size_t shift_index;
468         while ((shift_index = after_shift.find(SHIFT_TOKEN)) != std::string::npos) {
469           after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
470         }
471 
472         for (auto reg1 : reg1_registers) {
473           std::string after_reg1 = after_shift;
474 
475           std::string reg1_string = (this->*GetName1)(*reg1);
476           size_t reg1_index;
477           while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
478             after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
479           }
480 
481           for (auto reg2 : reg2_registers) {
482             std::string after_reg2 = after_reg1;
483 
484             std::string reg2_string = (this->*GetName2)(*reg2);
485             size_t reg2_index;
486             while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
487               after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
488             }
489 
490             if (first) {
491               first = false;
492             } else {
493               oss << "\n";
494             }
495             oss << after_reg2;
496 
497             (Base::GetAssembler()->*f)(*reg1, *reg2, shift, c);
498           }
499         }
500       }
501     }
502     // Add a newline at the end.
503     oss << "\n";
504 
505     return oss.str();
506   }
507 
508  protected:
AssemblerArmTest()509   explicit AssemblerArmTest() {}
510 
511   virtual std::vector<Cond>& GetConditions() = 0;
512   virtual std::string GetConditionString(Cond c) = 0;
513 
514   virtual std::vector<SOp>& GetShiftOperands() = 0;
515   virtual std::string GetShiftString(SOp sop) = 0;
516 
517   virtual Reg GetPCRegister() = 0;
GetRegistersWithoutPC()518   virtual std::vector<Reg*> GetRegistersWithoutPC() {
519     std::vector<Reg*> without_pc = GetRegisters();
520     Reg pc_reg = GetPCRegister();
521 
522     for (auto it = without_pc.begin(); it != without_pc.end(); ++it) {
523       if (**it == pc_reg) {
524         without_pc.erase(it);
525         break;
526       }
527     }
528 
529     return without_pc;
530   }
531 
532   static constexpr const char* IMM1_TOKEN = "{imm1}";
533   static constexpr const char* IMM2_TOKEN = "{imm2}";
534   static constexpr const char* REG3_TOKEN = "{reg3}";
535   static constexpr const char* REG4_TOKEN = "{reg4}";
536   static constexpr const char* COND_TOKEN = "{cond}";
537   static constexpr const char* SHIFT_TOKEN = "{shift}";
538 
539  private:
540   DISALLOW_COPY_AND_ASSIGN(AssemblerArmTest);
541 };
542 
543 }  // namespace art
544 
545 #endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
546