blob: 7c800b355febf92ac05474cdf3996ff28229a8de [file] [log] [blame]
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001/*
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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <sys/stat.h>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070023
24#include <cstdio>
25#include <cstdlib>
26#include <fstream>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070027#include <iterator>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070028
David Sehr3215fff2018-04-03 17:10:12 -070029#include "base/malloc_arena_pool.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070030#include "assembler_test_base.h"
31#include "common_runtime_test.h" // For ScratchFile
Andreas Gampe5a4fa822014-03-31 16:50:12 -070032
33namespace art {
34
Andreas Gampe851df202014-11-12 14:05:46 -080035// Helper for a constexpr string length.
36constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
37 return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
38}
39
Andreas Gampe849cc5e2014-11-18 13:46:46 -080040enum class RegisterView { // private
41 kUsePrimaryName,
Chao-ying Fud23840d2015-04-07 16:03:04 -070042 kUseSecondaryName,
43 kUseTertiaryName,
44 kUseQuaternaryName,
Andreas Gampe849cc5e2014-11-18 13:46:46 -080045};
46
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +000047// For use in the template as the default type to get a nonvector registers version.
48struct NoVectorRegs {};
49
Aart Bikcaa31e72017-09-14 17:08:50 -070050template<typename Ass,
51 typename Addr,
52 typename Reg,
53 typename FPReg,
54 typename Imm,
55 typename VecReg = NoVectorRegs>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070056class AssemblerTest : public testing::Test {
57 public:
58 Ass* GetAssembler() {
59 return assembler_.get();
60 }
61
Andreas Gampe851df202014-11-12 14:05:46 -080062 typedef std::string (*TestFn)(AssemblerTest* assembler_test, Ass* assembler);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070063
Andreas Gampe2e965ac2016-11-03 17:24:15 -070064 void DriverFn(TestFn f, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070065 DriverWrapper(f(this, assembler_.get()), test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070066 }
67
68 // This driver assumes the assembler has already been called.
Andreas Gampe2e965ac2016-11-03 17:24:15 -070069 void DriverStr(const std::string& assembly_string, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070070 DriverWrapper(assembly_string, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070071 }
72
Aart Bikcaa31e72017-09-14 17:08:50 -070073 //
74 // Register repeats.
75 //
76
Andreas Gampe2e965ac2016-11-03 17:24:15 -070077 std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080078 return RepeatTemplatedRegister<Reg>(f,
79 GetRegisters(),
80 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
81 fmt);
82 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070083
Andreas Gampe2e965ac2016-11-03 17:24:15 -070084 std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080085 return RepeatTemplatedRegister<Reg>(f,
86 GetRegisters(),
87 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
88 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070089 }
90
Andreas Gampe2e965ac2016-11-03 17:24:15 -070091 std::string RepeatRR(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080092 return RepeatTemplatedRegisters<Reg, Reg>(f,
93 GetRegisters(),
94 GetRegisters(),
95 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
96 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
97 fmt);
98 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070099
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700100 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -0700101 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
102 GetRegisters(),
103 GetRegisters(),
104 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
105 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
106 fmt);
107 }
108
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700109 std::string Repeatrr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800110 return RepeatTemplatedRegisters<Reg, Reg>(f,
111 GetRegisters(),
112 GetRegisters(),
113 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
114 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
115 fmt);
116 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700117
Aart Bikf7754e82017-09-20 10:33:06 -0700118 std::string Repeatww(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
119 return RepeatTemplatedRegisters<Reg, Reg>(f,
120 GetRegisters(),
121 GetRegisters(),
122 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
123 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
124 fmt);
125 }
126
127 std::string Repeatbb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
128 return RepeatTemplatedRegisters<Reg, Reg>(f,
129 GetRegisters(),
130 GetRegisters(),
131 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
132 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
133 fmt);
134 }
135
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700136 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700137 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
138 GetRegisters(),
139 GetRegisters(),
140 GetRegisters(),
141 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
142 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
143 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
144 fmt);
145 }
146
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700147 std::string Repeatrb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700148 return RepeatTemplatedRegisters<Reg, Reg>(f,
149 GetRegisters(),
150 GetRegisters(),
151 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
152 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
153 fmt);
154 }
155
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700156 std::string RepeatRr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800157 return RepeatTemplatedRegisters<Reg, Reg>(f,
158 GetRegisters(),
159 GetRegisters(),
160 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
161 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
162 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700163 }
164
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700165 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800166 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700167 }
168
Aart Bikf7754e82017-09-20 10:33:06 -0700169 std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800170 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
171 }
172
Aart Bikf7754e82017-09-20 10:33:06 -0700173 std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
174 return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
175 }
176
177 std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
178 return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
179 }
180
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200181 template <typename Reg1, typename Reg2, typename ImmType>
182 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
183 int imm_bits,
184 const std::vector<Reg1*> reg1_registers,
185 const std::vector<Reg2*> reg2_registers,
186 std::string (AssemblerTest::*GetName1)(const Reg1&),
187 std::string (AssemblerTest::*GetName2)(const Reg2&),
Chris Larsene3660592016-11-09 11:13:42 -0800188 const std::string& fmt,
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000189 int bias = 0,
190 int multiplier = 1) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700191 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800192 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Chris Larsendbce0d72015-09-17 13:34:00 -0700193
194 for (auto reg1 : reg1_registers) {
195 for (auto reg2 : reg2_registers) {
196 for (int64_t imm : imms) {
197 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700198 if (f != nullptr) {
199 (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
200 }
Chris Larsendbce0d72015-09-17 13:34:00 -0700201 std::string base = fmt;
202
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200203 std::string reg1_string = (this->*GetName1)(*reg1);
Chris Larsendbce0d72015-09-17 13:34:00 -0700204 size_t reg1_index;
205 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
206 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
207 }
208
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200209 std::string reg2_string = (this->*GetName2)(*reg2);
Chris Larsendbce0d72015-09-17 13:34:00 -0700210 size_t reg2_index;
211 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
212 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
213 }
214
215 size_t imm_index = base.find(IMM_TOKEN);
216 if (imm_index != std::string::npos) {
217 std::ostringstream sreg;
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000218 sreg << imm * multiplier + bias;
Chris Larsendbce0d72015-09-17 13:34:00 -0700219 std::string imm_string = sreg.str();
220 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
221 }
222
223 if (str.size() > 0) {
224 str += "\n";
225 }
226 str += base;
227 }
228 }
229 }
230 // Add a newline at the end.
231 str += "\n";
232 return str;
233 }
234
Chris Larsene3660592016-11-09 11:13:42 -0800235 template <typename Reg1, typename Reg2, typename Reg3, typename ImmType>
236 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType),
237 int imm_bits,
238 const std::vector<Reg1*> reg1_registers,
239 const std::vector<Reg2*> reg2_registers,
240 const std::vector<Reg3*> reg3_registers,
241 std::string (AssemblerTest::*GetName1)(const Reg1&),
242 std::string (AssemblerTest::*GetName2)(const Reg2&),
243 std::string (AssemblerTest::*GetName3)(const Reg3&),
244 std::string fmt,
245 int bias) {
246 std::string str;
247 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
248
249 for (auto reg1 : reg1_registers) {
250 for (auto reg2 : reg2_registers) {
251 for (auto reg3 : reg3_registers) {
252 for (int64_t imm : imms) {
253 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700254 if (f != nullptr) {
255 (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
256 }
Chris Larsene3660592016-11-09 11:13:42 -0800257 std::string base = fmt;
258
259 std::string reg1_string = (this->*GetName1)(*reg1);
260 size_t reg1_index;
261 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
262 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
263 }
264
265 std::string reg2_string = (this->*GetName2)(*reg2);
266 size_t reg2_index;
267 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
268 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
269 }
270
271 std::string reg3_string = (this->*GetName3)(*reg3);
272 size_t reg3_index;
273 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
274 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
275 }
276
277 size_t imm_index = base.find(IMM_TOKEN);
278 if (imm_index != std::string::npos) {
279 std::ostringstream sreg;
280 sreg << imm + bias;
281 std::string imm_string = sreg.str();
282 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
283 }
284
285 if (str.size() > 0) {
286 str += "\n";
287 }
288 str += base;
289 }
290 }
291 }
292 }
293 // Add a newline at the end.
294 str += "\n";
295 return str;
296 }
297
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800298 template <typename ImmType, typename Reg1, typename Reg2>
299 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
300 const std::vector<Reg1*> reg1_registers,
301 const std::vector<Reg2*> reg2_registers,
302 std::string (AssemblerTest::*GetName1)(const Reg1&),
303 std::string (AssemblerTest::*GetName2)(const Reg2&),
304 int imm_bits,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700305 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800306 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
307
308 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
309
310 std::string str;
311 for (auto reg1 : reg1_registers) {
312 for (auto reg2 : reg2_registers) {
313 for (int64_t imm : imms) {
314 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700315 if (f != nullptr) {
316 (assembler_.get()->*f)(new_imm, *reg1, *reg2);
317 }
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800318 std::string base = fmt;
319
320 std::string reg1_string = (this->*GetName1)(*reg1);
321 size_t reg1_index;
322 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
323 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
324 }
325
326 std::string reg2_string = (this->*GetName2)(*reg2);
327 size_t reg2_index;
328 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
329 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
330 }
331
332 size_t imm_index = base.find(IMM_TOKEN);
333 if (imm_index != std::string::npos) {
334 std::ostringstream sreg;
335 sreg << imm;
336 std::string imm_string = sreg.str();
337 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
338 }
339
340 if (str.size() > 0) {
341 str += "\n";
342 }
343 str += base;
344 }
345 }
346 }
347 // Add a newline at the end.
348 str += "\n";
349 return str;
350 }
351
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200352 template <typename RegType, typename ImmType>
353 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800354 int imm_bits,
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200355 const std::vector<RegType*> registers,
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800356 std::string (AssemblerTest::*GetName)(const RegType&),
Chris Larsene3660592016-11-09 11:13:42 -0800357 const std::string& fmt,
358 int bias) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200359 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800360 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200361
362 for (auto reg : registers) {
363 for (int64_t imm : imms) {
364 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700365 if (f != nullptr) {
366 (assembler_.get()->*f)(*reg, new_imm + bias);
367 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200368 std::string base = fmt;
369
370 std::string reg_string = (this->*GetName)(*reg);
371 size_t reg_index;
372 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
373 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
374 }
375
376 size_t imm_index = base.find(IMM_TOKEN);
377 if (imm_index != std::string::npos) {
378 std::ostringstream sreg;
Chris Larsene3660592016-11-09 11:13:42 -0800379 sreg << imm + bias;
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200380 std::string imm_string = sreg.str();
381 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
382 }
383
384 if (str.size() > 0) {
385 str += "\n";
386 }
387 str += base;
388 }
389 }
390 // Add a newline at the end.
391 str += "\n";
392 return str;
393 }
394
395 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800396 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
397 int imm_bits,
398 const std::string& fmt,
399 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200400 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
401 imm_bits,
402 GetRegisters(),
403 GetRegisters(),
404 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
405 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800406 fmt,
407 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200408 }
409
410 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800411 std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
412 int imm_bits,
413 const std::string& fmt,
414 int bias = 0) {
415 return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
416 imm_bits,
417 GetRegisters(),
418 GetRegisters(),
419 GetRegisters(),
420 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
421 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
422 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
423 fmt,
424 bias);
425 }
426
427 template <typename ImmType>
428 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200429 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
430 imm_bits,
431 GetRegisters(),
432 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800433 fmt,
434 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200435 }
436
437 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700438 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
439 int imm_bits,
Chris Larsene3660592016-11-09 11:13:42 -0800440 const std::string& fmt,
441 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200442 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
443 imm_bits,
444 GetFPRegisters(),
445 GetRegisters(),
446 &AssemblerTest::GetFPRegName,
447 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800448 fmt,
449 bias);
Chris Larsendbce0d72015-09-17 13:34:00 -0700450 }
451
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700452 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800453 return RepeatTemplatedRegisters<FPReg, FPReg>(f,
454 GetFPRegisters(),
455 GetFPRegisters(),
456 &AssemblerTest::GetFPRegName,
457 &AssemblerTest::GetFPRegName,
458 fmt);
459 }
460
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700461 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700462 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
463 GetFPRegisters(),
464 GetFPRegisters(),
465 GetFPRegisters(),
466 &AssemblerTest::GetFPRegName,
467 &AssemblerTest::GetFPRegName,
468 &AssemblerTest::GetFPRegName,
469 fmt);
470 }
471
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700472 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
Alexey Frunze674b9ee2016-09-20 14:54:15 -0700473 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
474 f,
475 GetFPRegisters(),
476 GetFPRegisters(),
477 GetRegisters(),
478 &AssemblerTest::GetFPRegName,
479 &AssemblerTest::GetFPRegName,
480 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
481 fmt);
482 }
483
Chris Larsendbce0d72015-09-17 13:34:00 -0700484 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
485 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700486 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400487 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
Chris Larsendbce0d72015-09-17 13:34:00 -0700488 GetFPRegisters(),
489 GetFPRegisters(),
490 &AssemblerTest::GetFPRegName,
491 &AssemblerTest::GetFPRegName,
492 imm_bytes,
493 fmt);
Mark Mendellfb8d2792015-03-31 22:16:59 -0400494 }
495
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800496 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700497 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
498 int imm_bits,
499 const std::string& fmt) {
Alexey Frunzea8aaf5a2016-06-27 14:48:20 -0700500 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
501 imm_bits,
502 GetFPRegisters(),
503 GetFPRegisters(),
504 &AssemblerTest::GetFPRegName,
505 &AssemblerTest::GetFPRegName,
506 fmt);
507 }
508
509 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700510 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
511 int imm_bits,
512 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800513 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
514 GetFPRegisters(),
515 GetFPRegisters(),
516 &AssemblerTest::GetFPRegName,
517 &AssemblerTest::GetFPRegName,
518 imm_bits,
519 fmt);
520 }
521
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700522 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800523 return RepeatTemplatedRegisters<FPReg, Reg>(f,
524 GetFPRegisters(),
525 GetRegisters(),
526 &AssemblerTest::GetFPRegName,
527 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
528 fmt);
529 }
530
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700531 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800532 return RepeatTemplatedRegisters<FPReg, Reg>(f,
533 GetFPRegisters(),
534 GetRegisters(),
535 &AssemblerTest::GetFPRegName,
536 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
537 fmt);
538 }
539
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700540 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800541 return RepeatTemplatedRegisters<Reg, FPReg>(f,
542 GetRegisters(),
543 GetFPRegisters(),
544 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
545 &AssemblerTest::GetFPRegName,
546 fmt);
547 }
548
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700549 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800550 return RepeatTemplatedRegisters<Reg, FPReg>(f,
551 GetRegisters(),
552 GetFPRegisters(),
553 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
554 &AssemblerTest::GetFPRegName,
555 fmt);
556 }
557
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700558 std::string RepeatI(void (Ass::*f)(const Imm&),
559 size_t imm_bytes,
560 const std::string& fmt,
Andreas Gampe851df202014-11-12 14:05:46 -0800561 bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700562 std::string str;
Andreas Gampe851df202014-11-12 14:05:46 -0800563 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800564
565 WarnOnCombinations(imms.size());
566
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700567 for (int64_t imm : imms) {
Ian Rogerscf7f1912014-10-22 22:06:39 -0700568 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700569 if (f != nullptr) {
570 (assembler_.get()->*f)(new_imm);
571 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700572 std::string base = fmt;
573
Andreas Gampe851df202014-11-12 14:05:46 -0800574 size_t imm_index = base.find(IMM_TOKEN);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700575 if (imm_index != std::string::npos) {
576 std::ostringstream sreg;
577 sreg << imm;
578 std::string imm_string = sreg.str();
Andreas Gampe851df202014-11-12 14:05:46 -0800579 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700580 }
581
582 if (str.size() > 0) {
583 str += "\n";
584 }
585 str += base;
586 }
587 // Add a newline at the end.
588 str += "\n";
589 return str;
590 }
591
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000592 std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
593 return RepeatTemplatedRegisters<VecReg, VecReg>(f,
594 GetVectorRegisters(),
595 GetVectorRegisters(),
596 &AssemblerTest::GetVecRegName,
597 &AssemblerTest::GetVecRegName,
598 fmt);
599 }
600
601 std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
602 return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
603 GetVectorRegisters(),
604 GetVectorRegisters(),
605 GetVectorRegisters(),
606 &AssemblerTest::GetVecRegName,
607 &AssemblerTest::GetVecRegName,
608 &AssemblerTest::GetVecRegName,
609 fmt);
610 }
611
612 std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
613 return RepeatTemplatedRegisters<VecReg, Reg>(
614 f,
615 GetVectorRegisters(),
616 GetRegisters(),
617 &AssemblerTest::GetVecRegName,
618 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
619 fmt);
620 }
621
622 template <typename ImmType>
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200623 std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
624 int imm_bits,
625 std::string fmt,
626 int bias = 0) {
627 return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
628 imm_bits,
629 GetVectorRegisters(),
630 &AssemblerTest::GetVecRegName,
631 fmt,
632 bias);
633 }
634
635 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000636 std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
637 int imm_bits,
638 const std::string& fmt,
639 int bias = 0,
640 int multiplier = 1) {
641 return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
642 f,
643 imm_bits,
644 GetVectorRegisters(),
645 GetRegisters(),
646 &AssemblerTest::GetVecRegName,
647 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
648 fmt,
649 bias,
650 multiplier);
651 }
652
653 template <typename ImmType>
Lena Djokic3309c012017-10-13 14:34:32 +0200654 std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
655 int imm_bits,
656 const std::string& fmt,
657 int bias = 0,
658 int multiplier = 1) {
659 return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
660 f,
661 imm_bits,
662 GetRegisters(),
663 GetVectorRegisters(),
664 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
665 &AssemblerTest::GetVecRegName,
666 fmt,
667 bias,
668 multiplier);
669 }
670
671 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000672 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
673 int imm_bits,
674 const std::string& fmt,
675 int bias = 0) {
676 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
677 imm_bits,
678 GetVectorRegisters(),
679 GetVectorRegisters(),
680 &AssemblerTest::GetVecRegName,
681 &AssemblerTest::GetVecRegName,
682 fmt,
683 bias);
684 }
685
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700686 // This is intended to be run as a test.
687 bool CheckTools() {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700688 return test_helper_->CheckTools();
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700689 }
690
Andreas Gampe851df202014-11-12 14:05:46 -0800691 // The following functions are public so that TestFn can use them...
692
Aart Bikcaa31e72017-09-14 17:08:50 -0700693 // Returns a vector of address used by any of the repeat methods
694 // involving an "A" (e.g. RepeatA).
695 virtual std::vector<Addr> GetAddresses() = 0;
696
697 // Returns a vector of registers used by any of the repeat methods
698 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800699 virtual std::vector<Reg*> GetRegisters() = 0;
700
Aart Bikcaa31e72017-09-14 17:08:50 -0700701 // Returns a vector of fp-registers used by any of the repeat methods
702 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800703 virtual std::vector<FPReg*> GetFPRegisters() {
704 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
705 UNREACHABLE();
706 }
707
Aart Bikcaa31e72017-09-14 17:08:50 -0700708 // Returns a vector of dedicated simd-registers used by any of the repeat
709 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000710 virtual std::vector<VecReg*> GetVectorRegisters() {
711 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
712 UNREACHABLE();
713 }
714
Andreas Gampe851df202014-11-12 14:05:46 -0800715 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
716 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
717 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
718 UNREACHABLE();
719 }
720
Chao-ying Fud23840d2015-04-07 16:03:04 -0700721 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
722 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
723 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
724 UNREACHABLE();
725 }
726
727 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
728 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
729 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
730 UNREACHABLE();
731 }
732
Calin Juravle9aec02f2014-11-18 23:06:35 +0000733 std::string GetRegisterName(const Reg& reg) {
734 return GetRegName<RegisterView::kUsePrimaryName>(reg);
735 }
736
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700737 protected:
Igor Murashkin2ffb7032017-11-08 13:35:21 -0800738 AssemblerTest() {}
Andreas Gampe851df202014-11-12 14:05:46 -0800739
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700740 void SetUp() OVERRIDE {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100741 allocator_.reset(new ArenaAllocator(&pool_));
742 assembler_.reset(CreateAssembler(allocator_.get()));
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700743 test_helper_.reset(
744 new AssemblerTestInfrastructure(GetArchitectureString(),
745 GetAssemblerCmdName(),
746 GetAssemblerParameters(),
747 GetObjdumpCmdName(),
748 GetObjdumpParameters(),
749 GetDisassembleCmdName(),
750 GetDisassembleParameters(),
751 GetAssemblyHeader()));
Andreas Gampeb40c6a72014-05-02 14:25:12 -0700752
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700753 SetUpHelpers();
754 }
755
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700756 void TearDown() OVERRIDE {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700757 test_helper_.reset(); // Clean up the helper.
Vladimir Marko93205e32016-04-13 11:59:46 +0100758 assembler_.reset();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100759 allocator_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700760 }
761
Chris Larsen3add9cb2016-04-14 14:01:33 -0700762 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100763 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
764 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700765 }
766
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700767 // Override this to set up any architecture-specific things, e.g., register vectors.
768 virtual void SetUpHelpers() {}
769
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700770 // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
771 virtual std::string GetArchitectureString() = 0;
772
773 // Get the name of the assembler, e.g., "as" by default.
774 virtual std::string GetAssemblerCmdName() {
775 return "as";
776 }
777
778 // Switches to the assembler command. Default none.
779 virtual std::string GetAssemblerParameters() {
780 return "";
781 }
782
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700783 // Get the name of the objdump, e.g., "objdump" by default.
784 virtual std::string GetObjdumpCmdName() {
785 return "objdump";
786 }
787
788 // Switches to the objdump command. Default is " -h".
789 virtual std::string GetObjdumpParameters() {
790 return " -h";
791 }
792
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700793 // Get the name of the objdump, e.g., "objdump" by default.
794 virtual std::string GetDisassembleCmdName() {
795 return "objdump";
796 }
797
798 // Switches to the objdump command. As it's a binary, one needs to push the architecture and
799 // such to objdump, so it's architecture-specific and there is no default.
800 virtual std::string GetDisassembleParameters() = 0;
801
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700802 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800803 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700804 std::vector<int64_t> res;
805 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800806 if (!as_uint) {
807 res.push_back(-1);
808 } else {
809 res.push_back(0xFF);
810 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700811 res.push_back(0x12);
812 if (imm_bytes >= 2) {
813 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800814 if (!as_uint) {
815 res.push_back(-0x1234);
816 } else {
817 res.push_back(0xFFFF);
818 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700819 if (imm_bytes >= 4) {
820 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800821 if (!as_uint) {
822 res.push_back(-0x12345678);
823 } else {
824 res.push_back(0xFFFFFFFF);
825 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700826 if (imm_bytes >= 6) {
827 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800828 if (!as_uint) {
829 res.push_back(-0x123456789ABC);
830 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700831 if (imm_bytes >= 8) {
832 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800833 if (!as_uint) {
834 res.push_back(-0x123456789ABCDEF0);
835 } else {
836 res.push_back(0xFFFFFFFFFFFFFFFF);
837 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700838 }
839 }
840 }
841 }
842 return res;
843 }
844
Chris Larsendbce0d72015-09-17 13:34:00 -0700845 const int kMaxBitsExhaustiveTest = 8;
846
847 // Create a couple of immediate values up to the number of bits given.
848 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
849 CHECK_GT(imm_bits, 0);
850 CHECK_LE(imm_bits, 64);
851 std::vector<int64_t> res;
852
853 if (imm_bits <= kMaxBitsExhaustiveTest) {
854 if (as_uint) {
855 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
856 res.push_back(static_cast<int64_t>(i));
857 }
858 } else {
859 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
860 res.push_back(i);
861 }
862 }
863 } else {
864 if (as_uint) {
865 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
866 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
867 i++) {
868 res.push_back(static_cast<int64_t>(i));
869 }
870 for (int i = 0; i <= imm_bits; i++) {
871 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
872 ((MaxInt<uint64_t>(imm_bits) -
873 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
874 * i / imm_bits);
875 res.push_back(static_cast<int64_t>(j));
876 }
877 } else {
878 for (int i = 0; i <= imm_bits; i++) {
879 int64_t j = MinInt<int64_t>(imm_bits) +
880 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
881 MinInt<int64_t>(imm_bits))
882 * i) / imm_bits);
883 res.push_back(static_cast<int64_t>(j));
884 }
885 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
886 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
887 i++) {
888 res.push_back(static_cast<int64_t>(i));
889 }
890 for (int i = 0; i <= imm_bits; i++) {
891 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
892 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
893 * i / imm_bits);
894 res.push_back(static_cast<int64_t>(j));
895 }
896 }
897 }
898
899 return res;
900 }
901
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700902 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700903 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700904
Aart Bikcaa31e72017-09-14 17:08:50 -0700905 //
906 // Addresses repeats.
907 //
908
909 // Repeats over addresses provided by fixture.
910 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
911 return RepeatA(f, GetAddresses(), fmt);
912 }
913
914 // Variant that takes explicit vector of addresss
915 // (to test restricted addressing modes set).
916 std::string RepeatA(void (Ass::*f)(const Addr&),
917 const std::vector<Addr>& a,
918 const std::string& fmt) {
919 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
920 }
921
922 // Repeats over addresses and immediates provided by fixture.
923 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
924 size_t imm_bytes,
925 const std::string& fmt) {
926 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
927 }
928
929 // Variant that takes explicit vector of addresss
930 // (to test restricted addressing modes set).
931 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
932 size_t imm_bytes,
933 const std::vector<Addr>& a,
934 const std::string& fmt) {
935 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
936 }
937
938 // Repeats over registers and addresses provided by fixture.
939 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
940 return RepeatRA(f, GetAddresses(), fmt);
941 }
942
943 // Variant that takes explicit vector of addresss
944 // (to test restricted addressing modes set).
945 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
946 const std::vector<Addr>& a,
947 const std::string& fmt) {
948 return RepeatTemplatedRegMem<Reg, Addr>(
949 f,
950 GetRegisters(),
951 a,
952 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
953 &AssemblerTest::GetAddrName,
954 fmt);
955 }
956
Aart Bikf7754e82017-09-20 10:33:06 -0700957 // Repeats over secondary registers and addresses provided by fixture.
958 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
959 return RepeatrA(f, GetAddresses(), fmt);
960 }
961
962 // Variant that takes explicit vector of addresss
963 // (to test restricted addressing modes set).
964 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
965 const std::vector<Addr>& a,
966 const std::string& fmt) {
967 return RepeatTemplatedRegMem<Reg, Addr>(
968 f,
969 GetRegisters(),
970 a,
971 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
972 &AssemblerTest::GetAddrName,
973 fmt);
974 }
975
976 // Repeats over tertiary registers and addresses provided by fixture.
977 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
978 return RepeatwA(f, GetAddresses(), fmt);
979 }
980
981 // Variant that takes explicit vector of addresss
982 // (to test restricted addressing modes set).
983 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
984 const std::vector<Addr>& a,
985 const std::string& fmt) {
986 return RepeatTemplatedRegMem<Reg, Addr>(
987 f,
988 GetRegisters(),
989 a,
990 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
991 &AssemblerTest::GetAddrName,
992 fmt);
993 }
994
995 // Repeats over quaternary registers and addresses provided by fixture.
996 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
997 return RepeatbA(f, GetAddresses(), fmt);
998 }
999
1000 // Variant that takes explicit vector of addresss
1001 // (to test restricted addressing modes set).
1002 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
1003 const std::vector<Addr>& a,
1004 const std::string& fmt) {
1005 return RepeatTemplatedRegMem<Reg, Addr>(
1006 f,
1007 GetRegisters(),
1008 a,
1009 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1010 &AssemblerTest::GetAddrName,
1011 fmt);
1012 }
1013
Aart Bikcaa31e72017-09-14 17:08:50 -07001014 // Repeats over fp-registers and addresses provided by fixture.
1015 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
1016 return RepeatFA(f, GetAddresses(), fmt);
1017 }
1018
1019 // Variant that takes explicit vector of addresss
1020 // (to test restricted addressing modes set).
1021 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1022 const std::vector<Addr>& a,
1023 const std::string& fmt) {
1024 return RepeatTemplatedRegMem<FPReg, Addr>(
1025 f,
1026 GetFPRegisters(),
1027 a,
1028 &AssemblerTest::GetFPRegName,
1029 &AssemblerTest::GetAddrName,
1030 fmt);
1031 }
1032
1033 // Repeats over addresses and registers provided by fixture.
1034 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1035 return RepeatAR(f, GetAddresses(), fmt);
1036 }
1037
1038 // Variant that takes explicit vector of addresss
1039 // (to test restricted addressing modes set).
1040 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1041 const std::vector<Addr>& a,
1042 const std::string& fmt) {
1043 return RepeatTemplatedMemReg<Addr, Reg>(
1044 f,
1045 a,
1046 GetRegisters(),
1047 &AssemblerTest::GetAddrName,
1048 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1049 fmt);
1050 }
1051
Aart Bikf7754e82017-09-20 10:33:06 -07001052 // Repeats over addresses and secondary registers provided by fixture.
1053 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1054 return RepeatAr(f, GetAddresses(), fmt);
1055 }
1056
1057 // Variant that takes explicit vector of addresss
1058 // (to test restricted addressing modes set).
1059 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1060 const std::vector<Addr>& a,
1061 const std::string& fmt) {
1062 return RepeatTemplatedMemReg<Addr, Reg>(
1063 f,
1064 a,
1065 GetRegisters(),
1066 &AssemblerTest::GetAddrName,
1067 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1068 fmt);
1069 }
1070
1071 // Repeats over addresses and tertiary registers provided by fixture.
1072 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1073 return RepeatAw(f, GetAddresses(), fmt);
1074 }
1075
1076 // Variant that takes explicit vector of addresss
1077 // (to test restricted addressing modes set).
1078 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1079 const std::vector<Addr>& a,
1080 const std::string& fmt) {
1081 return RepeatTemplatedMemReg<Addr, Reg>(
1082 f,
1083 a,
1084 GetRegisters(),
1085 &AssemblerTest::GetAddrName,
1086 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1087 fmt);
1088 }
1089
1090 // Repeats over addresses and quaternary registers provided by fixture.
1091 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1092 return RepeatAb(f, GetAddresses(), fmt);
1093 }
1094
1095 // Variant that takes explicit vector of addresss
1096 // (to test restricted addressing modes set).
1097 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1098 const std::vector<Addr>& a,
1099 const std::string& fmt) {
1100 return RepeatTemplatedMemReg<Addr, Reg>(
1101 f,
1102 a,
1103 GetRegisters(),
1104 &AssemblerTest::GetAddrName,
1105 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1106 fmt);
1107 }
1108
Aart Bikcaa31e72017-09-14 17:08:50 -07001109 // Repeats over addresses and fp-registers provided by fixture.
1110 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1111 return RepeatAF(f, GetAddresses(), fmt);
1112 }
1113
1114 // Variant that takes explicit vector of addresss
1115 // (to test restricted addressing modes set).
1116 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1117 const std::vector<Addr>& a,
1118 const std::string& fmt) {
1119 return RepeatTemplatedMemReg<Addr, FPReg>(
1120 f,
1121 a,
1122 GetFPRegisters(),
1123 &AssemblerTest::GetAddrName,
1124 &AssemblerTest::GetFPRegName,
1125 fmt);
1126 }
1127
1128 template <typename AddrType>
1129 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1130 const std::vector<AddrType> addresses,
1131 std::string (AssemblerTest::*GetAName)(const AddrType&),
1132 const std::string& fmt) {
1133 WarnOnCombinations(addresses.size());
1134 std::string str;
1135 for (auto addr : addresses) {
1136 if (f != nullptr) {
1137 (assembler_.get()->*f)(addr);
1138 }
1139 std::string base = fmt;
1140
1141 std::string addr_string = (this->*GetAName)(addr);
1142 size_t addr_index;
1143 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1144 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1145 }
1146
1147 if (str.size() > 0) {
1148 str += "\n";
1149 }
1150 str += base;
1151 }
1152 // Add a newline at the end.
1153 str += "\n";
1154 return str;
1155 }
1156
1157 template <typename AddrType>
1158 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1159 size_t imm_bytes,
1160 const std::vector<AddrType> addresses,
1161 std::string (AssemblerTest::*GetAName)(const AddrType&),
1162 const std::string& fmt) {
1163 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1164 WarnOnCombinations(addresses.size() * imms.size());
1165 std::string str;
1166 for (auto addr : addresses) {
1167 for (int64_t imm : imms) {
1168 Imm new_imm = CreateImmediate(imm);
1169 if (f != nullptr) {
1170 (assembler_.get()->*f)(addr, new_imm);
1171 }
1172 std::string base = fmt;
1173
1174 std::string addr_string = (this->*GetAName)(addr);
1175 size_t addr_index;
1176 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1177 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1178 }
1179
1180 size_t imm_index = base.find(IMM_TOKEN);
1181 if (imm_index != std::string::npos) {
1182 std::ostringstream sreg;
1183 sreg << imm;
1184 std::string imm_string = sreg.str();
1185 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1186 }
1187
1188 if (str.size() > 0) {
1189 str += "\n";
1190 }
1191 str += base;
1192 }
1193 }
1194 // Add a newline at the end.
1195 str += "\n";
1196 return str;
1197 }
1198
1199 template <typename RegType, typename AddrType>
1200 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1201 const std::vector<RegType*> registers,
1202 const std::vector<AddrType> addresses,
1203 std::string (AssemblerTest::*GetRName)(const RegType&),
1204 std::string (AssemblerTest::*GetAName)(const AddrType&),
1205 const std::string& fmt) {
1206 WarnOnCombinations(addresses.size() * registers.size());
1207 std::string str;
1208 for (auto reg : registers) {
1209 for (auto addr : addresses) {
1210 if (f != nullptr) {
1211 (assembler_.get()->*f)(*reg, addr);
1212 }
1213 std::string base = fmt;
1214
1215 std::string reg_string = (this->*GetRName)(*reg);
1216 size_t reg_index;
1217 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1218 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1219 }
1220
1221 std::string addr_string = (this->*GetAName)(addr);
1222 size_t addr_index;
1223 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1224 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1225 }
1226
1227 if (str.size() > 0) {
1228 str += "\n";
1229 }
1230 str += base;
1231 }
1232 }
1233 // Add a newline at the end.
1234 str += "\n";
1235 return str;
1236 }
1237
1238 template <typename AddrType, typename RegType>
1239 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1240 const std::vector<AddrType> addresses,
1241 const std::vector<RegType*> registers,
1242 std::string (AssemblerTest::*GetAName)(const AddrType&),
1243 std::string (AssemblerTest::*GetRName)(const RegType&),
1244 const std::string& fmt) {
1245 WarnOnCombinations(addresses.size() * registers.size());
1246 std::string str;
1247 for (auto addr : addresses) {
1248 for (auto reg : registers) {
1249 if (f != nullptr) {
1250 (assembler_.get()->*f)(addr, *reg);
1251 }
1252 std::string base = fmt;
1253
1254 std::string addr_string = (this->*GetAName)(addr);
1255 size_t addr_index;
1256 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1257 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1258 }
1259
1260 std::string reg_string = (this->*GetRName)(*reg);
1261 size_t reg_index;
1262 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1263 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1264 }
1265
1266 if (str.size() > 0) {
1267 str += "\n";
1268 }
1269 str += base;
1270 }
1271 }
1272 // Add a newline at the end.
1273 str += "\n";
1274 return str;
1275 }
1276
1277 //
1278 // Register repeats.
1279 //
1280
Andreas Gampe851df202014-11-12 14:05:46 -08001281 template <typename RegType>
1282 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1283 const std::vector<RegType*> registers,
1284 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001285 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001286 std::string str;
1287 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001288 if (f != nullptr) {
1289 (assembler_.get()->*f)(*reg);
1290 }
Andreas Gampe851df202014-11-12 14:05:46 -08001291 std::string base = fmt;
1292
1293 std::string reg_string = (this->*GetName)(*reg);
1294 size_t reg_index;
1295 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1296 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1297 }
1298
1299 if (str.size() > 0) {
1300 str += "\n";
1301 }
1302 str += base;
1303 }
1304 // Add a newline at the end.
1305 str += "\n";
1306 return str;
1307 }
1308
1309 template <typename Reg1, typename Reg2>
1310 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1311 const std::vector<Reg1*> reg1_registers,
1312 const std::vector<Reg2*> reg2_registers,
1313 std::string (AssemblerTest::*GetName1)(const Reg1&),
1314 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001315 const std::string& fmt) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001316 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1317
Andreas Gampe851df202014-11-12 14:05:46 -08001318 std::string str;
1319 for (auto reg1 : reg1_registers) {
1320 for (auto reg2 : reg2_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001321 if (f != nullptr) {
1322 (assembler_.get()->*f)(*reg1, *reg2);
1323 }
Andreas Gampe851df202014-11-12 14:05:46 -08001324 std::string base = fmt;
1325
1326 std::string reg1_string = (this->*GetName1)(*reg1);
1327 size_t reg1_index;
1328 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1329 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1330 }
1331
1332 std::string reg2_string = (this->*GetName2)(*reg2);
1333 size_t reg2_index;
1334 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1335 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1336 }
1337
1338 if (str.size() > 0) {
1339 str += "\n";
1340 }
1341 str += base;
1342 }
1343 }
1344 // Add a newline at the end.
1345 str += "\n";
1346 return str;
1347 }
1348
Chris Larsen51417632015-10-02 13:24:25 -07001349 template <typename Reg1, typename Reg2>
1350 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1351 const std::vector<Reg1*> reg1_registers,
1352 const std::vector<Reg2*> reg2_registers,
1353 std::string (AssemblerTest::*GetName1)(const Reg1&),
1354 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001355 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -07001356 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1357
1358 std::string str;
1359 for (auto reg1 : reg1_registers) {
1360 for (auto reg2 : reg2_registers) {
1361 if (reg1 == reg2) continue;
Aart Bik5dafb3c2017-09-13 13:10:12 -07001362 if (f != nullptr) {
1363 (assembler_.get()->*f)(*reg1, *reg2);
1364 }
Chris Larsen51417632015-10-02 13:24:25 -07001365 std::string base = fmt;
1366
1367 std::string reg1_string = (this->*GetName1)(*reg1);
1368 size_t reg1_index;
1369 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1370 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1371 }
1372
1373 std::string reg2_string = (this->*GetName2)(*reg2);
1374 size_t reg2_index;
1375 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1376 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1377 }
1378
1379 if (str.size() > 0) {
1380 str += "\n";
1381 }
1382 str += base;
1383 }
1384 }
1385 // Add a newline at the end.
1386 str += "\n";
1387 return str;
1388 }
1389
Chris Larsendbce0d72015-09-17 13:34:00 -07001390 template <typename Reg1, typename Reg2, typename Reg3>
1391 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1392 const std::vector<Reg1*> reg1_registers,
1393 const std::vector<Reg2*> reg2_registers,
1394 const std::vector<Reg3*> reg3_registers,
1395 std::string (AssemblerTest::*GetName1)(const Reg1&),
1396 std::string (AssemblerTest::*GetName2)(const Reg2&),
1397 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001398 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -07001399 std::string str;
1400 for (auto reg1 : reg1_registers) {
1401 for (auto reg2 : reg2_registers) {
1402 for (auto reg3 : reg3_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001403 if (f != nullptr) {
1404 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1405 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001406 std::string base = fmt;
1407
1408 std::string reg1_string = (this->*GetName1)(*reg1);
1409 size_t reg1_index;
1410 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1411 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1412 }
1413
1414 std::string reg2_string = (this->*GetName2)(*reg2);
1415 size_t reg2_index;
1416 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1417 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1418 }
1419
1420 std::string reg3_string = (this->*GetName3)(*reg3);
1421 size_t reg3_index;
1422 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
1423 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
1424 }
1425
1426 if (str.size() > 0) {
1427 str += "\n";
1428 }
1429 str += base;
1430 }
1431 }
1432 }
1433 // Add a newline at the end.
1434 str += "\n";
1435 return str;
1436 }
1437
Mark Mendellfb8d2792015-03-31 22:16:59 -04001438 template <typename Reg1, typename Reg2>
1439 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1440 const std::vector<Reg1*> reg1_registers,
1441 const std::vector<Reg2*> reg2_registers,
1442 std::string (AssemblerTest::*GetName1)(const Reg1&),
1443 std::string (AssemblerTest::*GetName2)(const Reg2&),
1444 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001445 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -04001446 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1447 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1448
1449 std::string str;
1450 for (auto reg1 : reg1_registers) {
1451 for (auto reg2 : reg2_registers) {
1452 for (int64_t imm : imms) {
1453 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001454 if (f != nullptr) {
1455 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1456 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001457 std::string base = fmt;
1458
1459 std::string reg1_string = (this->*GetName1)(*reg1);
1460 size_t reg1_index;
1461 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1462 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1463 }
1464
1465 std::string reg2_string = (this->*GetName2)(*reg2);
1466 size_t reg2_index;
1467 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1468 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1469 }
1470
1471 size_t imm_index = base.find(IMM_TOKEN);
1472 if (imm_index != std::string::npos) {
1473 std::ostringstream sreg;
1474 sreg << imm;
1475 std::string imm_string = sreg.str();
1476 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1477 }
1478
1479 if (str.size() > 0) {
1480 str += "\n";
1481 }
1482 str += base;
1483 }
1484 }
1485 }
1486 // Add a newline at the end.
1487 str += "\n";
1488 return str;
1489 }
1490
Aart Bikcaa31e72017-09-14 17:08:50 -07001491 std::string GetAddrName(const Addr& addr) {
1492 std::ostringstream saddr;
1493 saddr << addr;
1494 return saddr.str();
1495 }
1496
Andreas Gampe851df202014-11-12 14:05:46 -08001497 template <RegisterView kRegView>
1498 std::string GetRegName(const Reg& reg) {
1499 std::ostringstream sreg;
1500 switch (kRegView) {
1501 case RegisterView::kUsePrimaryName:
1502 sreg << reg;
1503 break;
1504
1505 case RegisterView::kUseSecondaryName:
1506 sreg << GetSecondaryRegisterName(reg);
1507 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -07001508
1509 case RegisterView::kUseTertiaryName:
1510 sreg << GetTertiaryRegisterName(reg);
1511 break;
1512
1513 case RegisterView::kUseQuaternaryName:
1514 sreg << GetQuaternaryRegisterName(reg);
1515 break;
Andreas Gampe851df202014-11-12 14:05:46 -08001516 }
1517 return sreg.str();
1518 }
1519
1520 std::string GetFPRegName(const FPReg& reg) {
1521 std::ostringstream sreg;
1522 sreg << reg;
1523 return sreg.str();
1524 }
1525
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001526 std::string GetVecRegName(const VecReg& reg) {
1527 std::ostringstream sreg;
1528 sreg << reg;
1529 return sreg.str();
1530 }
1531
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001532 // If the assembly file needs a header, return it in a sub-class.
1533 virtual const char* GetAssemblyHeader() {
1534 return nullptr;
1535 }
1536
1537 void WarnOnCombinations(size_t count) {
1538 if (count > kWarnManyCombinationsThreshold) {
1539 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1540 }
1541 }
1542
Aart Bikcaa31e72017-09-14 17:08:50 -07001543 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001544 static constexpr const char* REG_TOKEN = "{reg}";
1545 static constexpr const char* REG1_TOKEN = "{reg1}";
1546 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001547 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001548 static constexpr const char* IMM_TOKEN = "{imm}";
1549
1550 private:
Andreas Gampe851df202014-11-12 14:05:46 -08001551 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001552 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1553 size_t imm_bytes,
1554 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001555 const std::vector<Reg*> registers = GetRegisters();
1556 std::string str;
1557 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001558
1559 WarnOnCombinations(registers.size() * imms.size());
1560
Andreas Gampe851df202014-11-12 14:05:46 -08001561 for (auto reg : registers) {
1562 for (int64_t imm : imms) {
1563 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001564 if (f != nullptr) {
1565 (assembler_.get()->*f)(*reg, new_imm);
1566 }
Andreas Gampe851df202014-11-12 14:05:46 -08001567 std::string base = fmt;
1568
1569 std::string reg_string = GetRegName<kRegView>(*reg);
1570 size_t reg_index;
1571 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1572 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1573 }
1574
1575 size_t imm_index = base.find(IMM_TOKEN);
1576 if (imm_index != std::string::npos) {
1577 std::ostringstream sreg;
1578 sreg << imm;
1579 std::string imm_string = sreg.str();
1580 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1581 }
1582
1583 if (str.size() > 0) {
1584 str += "\n";
1585 }
1586 str += base;
1587 }
1588 }
1589 // Add a newline at the end.
1590 str += "\n";
1591 return str;
1592 }
1593
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001594 // Override this to pad the code with NOPs to a certain size if needed.
1595 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1596 }
1597
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001598 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001599 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001600 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001601 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001602 MemoryRegion code(&(*data)[0], data->size());
1603 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001604 Pad(*data);
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001605 test_helper_->Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001606 }
1607
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001608 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001609
David Sehr3215fff2018-04-03 17:10:12 -07001610 MallocArenaPool pool_;
Vladimir Marko69d310e2017-10-09 14:12:23 +01001611 std::unique_ptr<ArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -07001612 std::unique_ptr<Ass> assembler_;
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001613 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001614
Andreas Gampe851df202014-11-12 14:05:46 -08001615 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001616};
1617
1618} // namespace art
1619
1620#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_