blob: 9fffda57fd82176f8495ced50f571b50bf2a9972 [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>
David Srbeckyd6e14e02020-07-01 13:19:17 +010056class AssemblerTest : public AssemblerTestBase {
Andreas Gampe5a4fa822014-03-31 16:50:12 -070057 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 Gampe851df202014-11-12 14:05:46 -0800686 // The following functions are public so that TestFn can use them...
687
Aart Bikcaa31e72017-09-14 17:08:50 -0700688 // Returns a vector of address used by any of the repeat methods
689 // involving an "A" (e.g. RepeatA).
690 virtual std::vector<Addr> GetAddresses() = 0;
691
692 // Returns a vector of registers used by any of the repeat methods
693 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800694 virtual std::vector<Reg*> GetRegisters() = 0;
695
Aart Bikcaa31e72017-09-14 17:08:50 -0700696 // Returns a vector of fp-registers used by any of the repeat methods
697 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800698 virtual std::vector<FPReg*> GetFPRegisters() {
699 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
700 UNREACHABLE();
701 }
702
Aart Bikcaa31e72017-09-14 17:08:50 -0700703 // Returns a vector of dedicated simd-registers used by any of the repeat
704 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000705 virtual std::vector<VecReg*> GetVectorRegisters() {
706 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
707 UNREACHABLE();
708 }
709
Andreas Gampe851df202014-11-12 14:05:46 -0800710 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
711 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
712 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
713 UNREACHABLE();
714 }
715
Chao-ying Fud23840d2015-04-07 16:03:04 -0700716 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
717 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
718 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
719 UNREACHABLE();
720 }
721
722 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
723 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
724 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
725 UNREACHABLE();
726 }
727
Calin Juravle9aec02f2014-11-18 23:06:35 +0000728 std::string GetRegisterName(const Reg& reg) {
729 return GetRegName<RegisterView::kUsePrimaryName>(reg);
730 }
731
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700732 protected:
Igor Murashkin2ffb7032017-11-08 13:35:21 -0800733 AssemblerTest() {}
Andreas Gampe851df202014-11-12 14:05:46 -0800734
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100735 void SetUp() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100736 AssemblerTestBase::SetUp();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100737 allocator_.reset(new ArenaAllocator(&pool_));
738 assembler_.reset(CreateAssembler(allocator_.get()));
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700739 SetUpHelpers();
740 }
741
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100742 void TearDown() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100743 AssemblerTestBase::TearDown();
Vladimir Marko93205e32016-04-13 11:59:46 +0100744 assembler_.reset();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100745 allocator_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700746 }
747
Chris Larsen3add9cb2016-04-14 14:01:33 -0700748 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100749 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
750 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700751 }
752
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700753 // Override this to set up any architecture-specific things, e.g., register vectors.
754 virtual void SetUpHelpers() {}
755
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700756 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800757 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700758 std::vector<int64_t> res;
759 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800760 if (!as_uint) {
761 res.push_back(-1);
762 } else {
763 res.push_back(0xFF);
764 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700765 res.push_back(0x12);
766 if (imm_bytes >= 2) {
767 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800768 if (!as_uint) {
769 res.push_back(-0x1234);
770 } else {
771 res.push_back(0xFFFF);
772 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700773 if (imm_bytes >= 4) {
774 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800775 if (!as_uint) {
776 res.push_back(-0x12345678);
777 } else {
778 res.push_back(0xFFFFFFFF);
779 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700780 if (imm_bytes >= 6) {
781 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800782 if (!as_uint) {
783 res.push_back(-0x123456789ABC);
784 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700785 if (imm_bytes >= 8) {
786 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800787 if (!as_uint) {
788 res.push_back(-0x123456789ABCDEF0);
789 } else {
790 res.push_back(0xFFFFFFFFFFFFFFFF);
791 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700792 }
793 }
794 }
795 }
796 return res;
797 }
798
Chris Larsendbce0d72015-09-17 13:34:00 -0700799 const int kMaxBitsExhaustiveTest = 8;
800
801 // Create a couple of immediate values up to the number of bits given.
802 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
803 CHECK_GT(imm_bits, 0);
804 CHECK_LE(imm_bits, 64);
805 std::vector<int64_t> res;
806
807 if (imm_bits <= kMaxBitsExhaustiveTest) {
808 if (as_uint) {
809 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
810 res.push_back(static_cast<int64_t>(i));
811 }
812 } else {
813 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
814 res.push_back(i);
815 }
816 }
817 } else {
818 if (as_uint) {
819 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
820 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
821 i++) {
822 res.push_back(static_cast<int64_t>(i));
823 }
824 for (int i = 0; i <= imm_bits; i++) {
825 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
826 ((MaxInt<uint64_t>(imm_bits) -
827 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
828 * i / imm_bits);
829 res.push_back(static_cast<int64_t>(j));
830 }
831 } else {
832 for (int i = 0; i <= imm_bits; i++) {
833 int64_t j = MinInt<int64_t>(imm_bits) +
834 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
835 MinInt<int64_t>(imm_bits))
836 * i) / imm_bits);
837 res.push_back(static_cast<int64_t>(j));
838 }
839 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
840 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
841 i++) {
842 res.push_back(static_cast<int64_t>(i));
843 }
844 for (int i = 0; i <= imm_bits; i++) {
845 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
846 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
847 * i / imm_bits);
848 res.push_back(static_cast<int64_t>(j));
849 }
850 }
851 }
852
853 return res;
854 }
855
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700856 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700857 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700858
Aart Bikcaa31e72017-09-14 17:08:50 -0700859 //
860 // Addresses repeats.
861 //
862
863 // Repeats over addresses provided by fixture.
864 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
865 return RepeatA(f, GetAddresses(), fmt);
866 }
867
868 // Variant that takes explicit vector of addresss
869 // (to test restricted addressing modes set).
870 std::string RepeatA(void (Ass::*f)(const Addr&),
871 const std::vector<Addr>& a,
872 const std::string& fmt) {
873 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
874 }
875
876 // Repeats over addresses and immediates provided by fixture.
877 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
878 size_t imm_bytes,
879 const std::string& fmt) {
880 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
881 }
882
883 // Variant that takes explicit vector of addresss
884 // (to test restricted addressing modes set).
885 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
886 size_t imm_bytes,
887 const std::vector<Addr>& a,
888 const std::string& fmt) {
889 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
890 }
891
892 // Repeats over registers and addresses provided by fixture.
893 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
894 return RepeatRA(f, GetAddresses(), fmt);
895 }
896
897 // Variant that takes explicit vector of addresss
898 // (to test restricted addressing modes set).
899 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
900 const std::vector<Addr>& a,
901 const std::string& fmt) {
902 return RepeatTemplatedRegMem<Reg, Addr>(
903 f,
904 GetRegisters(),
905 a,
906 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
907 &AssemblerTest::GetAddrName,
908 fmt);
909 }
910
Aart Bikf7754e82017-09-20 10:33:06 -0700911 // Repeats over secondary registers and addresses provided by fixture.
912 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
913 return RepeatrA(f, GetAddresses(), fmt);
914 }
915
916 // Variant that takes explicit vector of addresss
917 // (to test restricted addressing modes set).
918 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
919 const std::vector<Addr>& a,
920 const std::string& fmt) {
921 return RepeatTemplatedRegMem<Reg, Addr>(
922 f,
923 GetRegisters(),
924 a,
925 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
926 &AssemblerTest::GetAddrName,
927 fmt);
928 }
929
930 // Repeats over tertiary registers and addresses provided by fixture.
931 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
932 return RepeatwA(f, GetAddresses(), fmt);
933 }
934
935 // Variant that takes explicit vector of addresss
936 // (to test restricted addressing modes set).
937 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
938 const std::vector<Addr>& a,
939 const std::string& fmt) {
940 return RepeatTemplatedRegMem<Reg, Addr>(
941 f,
942 GetRegisters(),
943 a,
944 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
945 &AssemblerTest::GetAddrName,
946 fmt);
947 }
948
949 // Repeats over quaternary registers and addresses provided by fixture.
950 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
951 return RepeatbA(f, GetAddresses(), fmt);
952 }
953
954 // Variant that takes explicit vector of addresss
955 // (to test restricted addressing modes set).
956 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
957 const std::vector<Addr>& a,
958 const std::string& fmt) {
959 return RepeatTemplatedRegMem<Reg, Addr>(
960 f,
961 GetRegisters(),
962 a,
963 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
964 &AssemblerTest::GetAddrName,
965 fmt);
966 }
967
Aart Bikcaa31e72017-09-14 17:08:50 -0700968 // Repeats over fp-registers and addresses provided by fixture.
969 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
970 return RepeatFA(f, GetAddresses(), fmt);
971 }
972
973 // Variant that takes explicit vector of addresss
974 // (to test restricted addressing modes set).
975 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
976 const std::vector<Addr>& a,
977 const std::string& fmt) {
978 return RepeatTemplatedRegMem<FPReg, Addr>(
979 f,
980 GetFPRegisters(),
981 a,
982 &AssemblerTest::GetFPRegName,
983 &AssemblerTest::GetAddrName,
984 fmt);
985 }
986
987 // Repeats over addresses and registers provided by fixture.
988 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
989 return RepeatAR(f, GetAddresses(), fmt);
990 }
991
992 // Variant that takes explicit vector of addresss
993 // (to test restricted addressing modes set).
994 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
995 const std::vector<Addr>& a,
996 const std::string& fmt) {
997 return RepeatTemplatedMemReg<Addr, Reg>(
998 f,
999 a,
1000 GetRegisters(),
1001 &AssemblerTest::GetAddrName,
1002 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1003 fmt);
1004 }
1005
Aart Bikf7754e82017-09-20 10:33:06 -07001006 // Repeats over addresses and secondary registers provided by fixture.
1007 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1008 return RepeatAr(f, GetAddresses(), fmt);
1009 }
1010
1011 // Variant that takes explicit vector of addresss
1012 // (to test restricted addressing modes set).
1013 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1014 const std::vector<Addr>& a,
1015 const std::string& fmt) {
1016 return RepeatTemplatedMemReg<Addr, Reg>(
1017 f,
1018 a,
1019 GetRegisters(),
1020 &AssemblerTest::GetAddrName,
1021 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1022 fmt);
1023 }
1024
1025 // Repeats over addresses and tertiary registers provided by fixture.
1026 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1027 return RepeatAw(f, GetAddresses(), fmt);
1028 }
1029
1030 // Variant that takes explicit vector of addresss
1031 // (to test restricted addressing modes set).
1032 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1033 const std::vector<Addr>& a,
1034 const std::string& fmt) {
1035 return RepeatTemplatedMemReg<Addr, Reg>(
1036 f,
1037 a,
1038 GetRegisters(),
1039 &AssemblerTest::GetAddrName,
1040 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1041 fmt);
1042 }
1043
1044 // Repeats over addresses and quaternary registers provided by fixture.
1045 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1046 return RepeatAb(f, GetAddresses(), fmt);
1047 }
1048
1049 // Variant that takes explicit vector of addresss
1050 // (to test restricted addressing modes set).
1051 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1052 const std::vector<Addr>& a,
1053 const std::string& fmt) {
1054 return RepeatTemplatedMemReg<Addr, Reg>(
1055 f,
1056 a,
1057 GetRegisters(),
1058 &AssemblerTest::GetAddrName,
1059 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1060 fmt);
1061 }
1062
Aart Bikcaa31e72017-09-14 17:08:50 -07001063 // Repeats over addresses and fp-registers provided by fixture.
1064 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1065 return RepeatAF(f, GetAddresses(), fmt);
1066 }
1067
1068 // Variant that takes explicit vector of addresss
1069 // (to test restricted addressing modes set).
1070 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1071 const std::vector<Addr>& a,
1072 const std::string& fmt) {
1073 return RepeatTemplatedMemReg<Addr, FPReg>(
1074 f,
1075 a,
1076 GetFPRegisters(),
1077 &AssemblerTest::GetAddrName,
1078 &AssemblerTest::GetFPRegName,
1079 fmt);
1080 }
1081
1082 template <typename AddrType>
1083 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1084 const std::vector<AddrType> addresses,
1085 std::string (AssemblerTest::*GetAName)(const AddrType&),
1086 const std::string& fmt) {
1087 WarnOnCombinations(addresses.size());
1088 std::string str;
1089 for (auto addr : addresses) {
1090 if (f != nullptr) {
1091 (assembler_.get()->*f)(addr);
1092 }
1093 std::string base = fmt;
1094
1095 std::string addr_string = (this->*GetAName)(addr);
1096 size_t addr_index;
1097 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1098 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1099 }
1100
1101 if (str.size() > 0) {
1102 str += "\n";
1103 }
1104 str += base;
1105 }
1106 // Add a newline at the end.
1107 str += "\n";
1108 return str;
1109 }
1110
1111 template <typename AddrType>
1112 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1113 size_t imm_bytes,
1114 const std::vector<AddrType> addresses,
1115 std::string (AssemblerTest::*GetAName)(const AddrType&),
1116 const std::string& fmt) {
1117 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1118 WarnOnCombinations(addresses.size() * imms.size());
1119 std::string str;
1120 for (auto addr : addresses) {
1121 for (int64_t imm : imms) {
1122 Imm new_imm = CreateImmediate(imm);
1123 if (f != nullptr) {
1124 (assembler_.get()->*f)(addr, new_imm);
1125 }
1126 std::string base = fmt;
1127
1128 std::string addr_string = (this->*GetAName)(addr);
1129 size_t addr_index;
1130 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1131 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1132 }
1133
1134 size_t imm_index = base.find(IMM_TOKEN);
1135 if (imm_index != std::string::npos) {
1136 std::ostringstream sreg;
1137 sreg << imm;
1138 std::string imm_string = sreg.str();
1139 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1140 }
1141
1142 if (str.size() > 0) {
1143 str += "\n";
1144 }
1145 str += base;
1146 }
1147 }
1148 // Add a newline at the end.
1149 str += "\n";
1150 return str;
1151 }
1152
1153 template <typename RegType, typename AddrType>
1154 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1155 const std::vector<RegType*> registers,
1156 const std::vector<AddrType> addresses,
1157 std::string (AssemblerTest::*GetRName)(const RegType&),
1158 std::string (AssemblerTest::*GetAName)(const AddrType&),
1159 const std::string& fmt) {
1160 WarnOnCombinations(addresses.size() * registers.size());
1161 std::string str;
1162 for (auto reg : registers) {
1163 for (auto addr : addresses) {
1164 if (f != nullptr) {
1165 (assembler_.get()->*f)(*reg, addr);
1166 }
1167 std::string base = fmt;
1168
1169 std::string reg_string = (this->*GetRName)(*reg);
1170 size_t reg_index;
1171 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1172 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1173 }
1174
1175 std::string addr_string = (this->*GetAName)(addr);
1176 size_t addr_index;
1177 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1178 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1179 }
1180
1181 if (str.size() > 0) {
1182 str += "\n";
1183 }
1184 str += base;
1185 }
1186 }
1187 // Add a newline at the end.
1188 str += "\n";
1189 return str;
1190 }
1191
1192 template <typename AddrType, typename RegType>
1193 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1194 const std::vector<AddrType> addresses,
1195 const std::vector<RegType*> registers,
1196 std::string (AssemblerTest::*GetAName)(const AddrType&),
1197 std::string (AssemblerTest::*GetRName)(const RegType&),
1198 const std::string& fmt) {
1199 WarnOnCombinations(addresses.size() * registers.size());
1200 std::string str;
1201 for (auto addr : addresses) {
1202 for (auto reg : registers) {
1203 if (f != nullptr) {
1204 (assembler_.get()->*f)(addr, *reg);
1205 }
1206 std::string base = fmt;
1207
1208 std::string addr_string = (this->*GetAName)(addr);
1209 size_t addr_index;
1210 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1211 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1212 }
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 if (str.size() > 0) {
1221 str += "\n";
1222 }
1223 str += base;
1224 }
1225 }
1226 // Add a newline at the end.
1227 str += "\n";
1228 return str;
1229 }
1230
1231 //
1232 // Register repeats.
1233 //
1234
Andreas Gampe851df202014-11-12 14:05:46 -08001235 template <typename RegType>
1236 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1237 const std::vector<RegType*> registers,
1238 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001239 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001240 std::string str;
1241 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001242 if (f != nullptr) {
1243 (assembler_.get()->*f)(*reg);
1244 }
Andreas Gampe851df202014-11-12 14:05:46 -08001245 std::string base = fmt;
1246
1247 std::string reg_string = (this->*GetName)(*reg);
1248 size_t reg_index;
1249 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1250 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1251 }
1252
1253 if (str.size() > 0) {
1254 str += "\n";
1255 }
1256 str += base;
1257 }
1258 // Add a newline at the end.
1259 str += "\n";
1260 return str;
1261 }
1262
1263 template <typename Reg1, typename Reg2>
1264 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1265 const std::vector<Reg1*> reg1_registers,
1266 const std::vector<Reg2*> reg2_registers,
1267 std::string (AssemblerTest::*GetName1)(const Reg1&),
1268 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001269 const std::string& fmt) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001270 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1271
Andreas Gampe851df202014-11-12 14:05:46 -08001272 std::string str;
1273 for (auto reg1 : reg1_registers) {
1274 for (auto reg2 : reg2_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001275 if (f != nullptr) {
1276 (assembler_.get()->*f)(*reg1, *reg2);
1277 }
Andreas Gampe851df202014-11-12 14:05:46 -08001278 std::string base = fmt;
1279
1280 std::string reg1_string = (this->*GetName1)(*reg1);
1281 size_t reg1_index;
1282 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1283 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1284 }
1285
1286 std::string reg2_string = (this->*GetName2)(*reg2);
1287 size_t reg2_index;
1288 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1289 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1290 }
1291
1292 if (str.size() > 0) {
1293 str += "\n";
1294 }
1295 str += base;
1296 }
1297 }
1298 // Add a newline at the end.
1299 str += "\n";
1300 return str;
1301 }
1302
Chris Larsen51417632015-10-02 13:24:25 -07001303 template <typename Reg1, typename Reg2>
1304 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1305 const std::vector<Reg1*> reg1_registers,
1306 const std::vector<Reg2*> reg2_registers,
1307 std::string (AssemblerTest::*GetName1)(const Reg1&),
1308 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001309 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -07001310 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1311
1312 std::string str;
1313 for (auto reg1 : reg1_registers) {
1314 for (auto reg2 : reg2_registers) {
1315 if (reg1 == reg2) continue;
Aart Bik5dafb3c2017-09-13 13:10:12 -07001316 if (f != nullptr) {
1317 (assembler_.get()->*f)(*reg1, *reg2);
1318 }
Chris Larsen51417632015-10-02 13:24:25 -07001319 std::string base = fmt;
1320
1321 std::string reg1_string = (this->*GetName1)(*reg1);
1322 size_t reg1_index;
1323 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1324 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1325 }
1326
1327 std::string reg2_string = (this->*GetName2)(*reg2);
1328 size_t reg2_index;
1329 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1330 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1331 }
1332
1333 if (str.size() > 0) {
1334 str += "\n";
1335 }
1336 str += base;
1337 }
1338 }
1339 // Add a newline at the end.
1340 str += "\n";
1341 return str;
1342 }
1343
Chris Larsendbce0d72015-09-17 13:34:00 -07001344 template <typename Reg1, typename Reg2, typename Reg3>
1345 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1346 const std::vector<Reg1*> reg1_registers,
1347 const std::vector<Reg2*> reg2_registers,
1348 const std::vector<Reg3*> reg3_registers,
1349 std::string (AssemblerTest::*GetName1)(const Reg1&),
1350 std::string (AssemblerTest::*GetName2)(const Reg2&),
1351 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001352 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -07001353 std::string str;
1354 for (auto reg1 : reg1_registers) {
1355 for (auto reg2 : reg2_registers) {
1356 for (auto reg3 : reg3_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001357 if (f != nullptr) {
1358 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1359 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001360 std::string base = fmt;
1361
1362 std::string reg1_string = (this->*GetName1)(*reg1);
1363 size_t reg1_index;
1364 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1365 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1366 }
1367
1368 std::string reg2_string = (this->*GetName2)(*reg2);
1369 size_t reg2_index;
1370 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1371 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1372 }
1373
1374 std::string reg3_string = (this->*GetName3)(*reg3);
1375 size_t reg3_index;
1376 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
1377 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
1378 }
1379
1380 if (str.size() > 0) {
1381 str += "\n";
1382 }
1383 str += base;
1384 }
1385 }
1386 }
1387 // Add a newline at the end.
1388 str += "\n";
1389 return str;
1390 }
1391
Mark Mendellfb8d2792015-03-31 22:16:59 -04001392 template <typename Reg1, typename Reg2>
1393 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1394 const std::vector<Reg1*> reg1_registers,
1395 const std::vector<Reg2*> reg2_registers,
1396 std::string (AssemblerTest::*GetName1)(const Reg1&),
1397 std::string (AssemblerTest::*GetName2)(const Reg2&),
1398 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001399 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -04001400 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1401 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1402
1403 std::string str;
1404 for (auto reg1 : reg1_registers) {
1405 for (auto reg2 : reg2_registers) {
1406 for (int64_t imm : imms) {
1407 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001408 if (f != nullptr) {
1409 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1410 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001411 std::string base = fmt;
1412
1413 std::string reg1_string = (this->*GetName1)(*reg1);
1414 size_t reg1_index;
1415 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1416 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1417 }
1418
1419 std::string reg2_string = (this->*GetName2)(*reg2);
1420 size_t reg2_index;
1421 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1422 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1423 }
1424
1425 size_t imm_index = base.find(IMM_TOKEN);
1426 if (imm_index != std::string::npos) {
1427 std::ostringstream sreg;
1428 sreg << imm;
1429 std::string imm_string = sreg.str();
1430 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1431 }
1432
1433 if (str.size() > 0) {
1434 str += "\n";
1435 }
1436 str += base;
1437 }
1438 }
1439 }
1440 // Add a newline at the end.
1441 str += "\n";
1442 return str;
1443 }
1444
Aart Bikcaa31e72017-09-14 17:08:50 -07001445 std::string GetAddrName(const Addr& addr) {
1446 std::ostringstream saddr;
1447 saddr << addr;
1448 return saddr.str();
1449 }
1450
Andreas Gampe851df202014-11-12 14:05:46 -08001451 template <RegisterView kRegView>
1452 std::string GetRegName(const Reg& reg) {
1453 std::ostringstream sreg;
1454 switch (kRegView) {
1455 case RegisterView::kUsePrimaryName:
1456 sreg << reg;
1457 break;
1458
1459 case RegisterView::kUseSecondaryName:
1460 sreg << GetSecondaryRegisterName(reg);
1461 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -07001462
1463 case RegisterView::kUseTertiaryName:
1464 sreg << GetTertiaryRegisterName(reg);
1465 break;
1466
1467 case RegisterView::kUseQuaternaryName:
1468 sreg << GetQuaternaryRegisterName(reg);
1469 break;
Andreas Gampe851df202014-11-12 14:05:46 -08001470 }
1471 return sreg.str();
1472 }
1473
1474 std::string GetFPRegName(const FPReg& reg) {
1475 std::ostringstream sreg;
1476 sreg << reg;
1477 return sreg.str();
1478 }
1479
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001480 std::string GetVecRegName(const VecReg& reg) {
1481 std::ostringstream sreg;
1482 sreg << reg;
1483 return sreg.str();
1484 }
1485
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001486 void WarnOnCombinations(size_t count) {
1487 if (count > kWarnManyCombinationsThreshold) {
1488 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1489 }
1490 }
1491
Aart Bikcaa31e72017-09-14 17:08:50 -07001492 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001493 static constexpr const char* REG_TOKEN = "{reg}";
1494 static constexpr const char* REG1_TOKEN = "{reg1}";
1495 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001496 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001497 static constexpr const char* IMM_TOKEN = "{imm}";
1498
1499 private:
Andreas Gampe851df202014-11-12 14:05:46 -08001500 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001501 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1502 size_t imm_bytes,
1503 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001504 const std::vector<Reg*> registers = GetRegisters();
1505 std::string str;
1506 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001507
1508 WarnOnCombinations(registers.size() * imms.size());
1509
Andreas Gampe851df202014-11-12 14:05:46 -08001510 for (auto reg : registers) {
1511 for (int64_t imm : imms) {
1512 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001513 if (f != nullptr) {
1514 (assembler_.get()->*f)(*reg, new_imm);
1515 }
Andreas Gampe851df202014-11-12 14:05:46 -08001516 std::string base = fmt;
1517
1518 std::string reg_string = GetRegName<kRegView>(*reg);
1519 size_t reg_index;
1520 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1521 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1522 }
1523
1524 size_t imm_index = base.find(IMM_TOKEN);
1525 if (imm_index != std::string::npos) {
1526 std::ostringstream sreg;
1527 sreg << imm;
1528 std::string imm_string = sreg.str();
1529 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1530 }
1531
1532 if (str.size() > 0) {
1533 str += "\n";
1534 }
1535 str += base;
1536 }
1537 }
1538 // Add a newline at the end.
1539 str += "\n";
1540 return str;
1541 }
1542
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001543 // Override this to pad the code with NOPs to a certain size if needed.
1544 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1545 }
1546
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001547 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001548 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001549 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001550 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001551 MemoryRegion code(&(*data)[0], data->size());
1552 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001553 Pad(*data);
David Srbeckyd6e14e02020-07-01 13:19:17 +01001554 Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001555 }
1556
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001557 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001558
David Sehr3215fff2018-04-03 17:10:12 -07001559 MallocArenaPool pool_;
Vladimir Marko69d310e2017-10-09 14:12:23 +01001560 std::unique_ptr<ArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -07001561 std::unique_ptr<Ass> assembler_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001562
Andreas Gampe851df202014-11-12 14:05:46 -08001563 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001564};
1565
1566} // namespace art
1567
1568#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_