blob: bb22fe5bded43e1f05a3514d555d5ab7c9762060 [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
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +010091 std::string RepeatRR(void (Ass::*f)(Reg, Reg),
92 const std::string& fmt,
93 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -080094 return RepeatTemplatedRegisters<Reg, Reg>(f,
95 GetRegisters(),
96 GetRegisters(),
97 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
98 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +010099 fmt,
100 except);
Andreas Gampe851df202014-11-12 14:05:46 -0800101 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700102
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700103 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -0700104 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
105 GetRegisters(),
106 GetRegisters(),
107 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
108 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
109 fmt);
110 }
111
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100112 std::string Repeatrr(void (Ass::*f)(Reg, Reg),
113 const std::string& fmt,
114 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -0800115 return RepeatTemplatedRegisters<Reg, Reg>(f,
116 GetRegisters(),
117 GetRegisters(),
118 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
119 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100120 fmt,
121 except);
Andreas Gampe851df202014-11-12 14:05:46 -0800122 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700123
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100124 std::string Repeatww(void (Ass::*f)(Reg, Reg),
125 const std::string& fmt,
126 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Aart Bikf7754e82017-09-20 10:33:06 -0700127 return RepeatTemplatedRegisters<Reg, Reg>(f,
128 GetRegisters(),
129 GetRegisters(),
130 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
131 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100132 fmt,
133 except);
Aart Bikf7754e82017-09-20 10:33:06 -0700134 }
135
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100136 std::string Repeatbb(void (Ass::*f)(Reg, Reg),
137 const std::string& fmt,
138 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Aart Bikf7754e82017-09-20 10:33:06 -0700139 return RepeatTemplatedRegisters<Reg, Reg>(f,
140 GetRegisters(),
141 GetRegisters(),
142 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
143 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100144 fmt,
145 except);
Aart Bikf7754e82017-09-20 10:33:06 -0700146 }
147
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700148 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700149 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
150 GetRegisters(),
151 GetRegisters(),
152 GetRegisters(),
153 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
154 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
155 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
156 fmt);
157 }
158
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100159 std::string Repeatrb(void (Ass::*f)(Reg, Reg),
160 const std::string& fmt,
161 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700162 return RepeatTemplatedRegisters<Reg, Reg>(f,
163 GetRegisters(),
164 GetRegisters(),
165 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
166 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100167 fmt,
168 except);
Chao-ying Fud23840d2015-04-07 16:03:04 -0700169 }
170
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100171 std::string RepeatRr(void (Ass::*f)(Reg, Reg),
172 const std::string& fmt,
173 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -0800174 return RepeatTemplatedRegisters<Reg, Reg>(f,
175 GetRegisters(),
176 GetRegisters(),
177 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
178 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100179 fmt,
180 except);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700181 }
182
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700183 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800184 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700185 }
186
Aart Bikf7754e82017-09-20 10:33:06 -0700187 std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800188 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
189 }
190
Aart Bikf7754e82017-09-20 10:33:06 -0700191 std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
192 return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
193 }
194
195 std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
196 return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
197 }
198
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200199 template <typename Reg1, typename Reg2, typename ImmType>
200 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
201 int imm_bits,
202 const std::vector<Reg1*> reg1_registers,
203 const std::vector<Reg2*> reg2_registers,
204 std::string (AssemblerTest::*GetName1)(const Reg1&),
205 std::string (AssemblerTest::*GetName2)(const Reg2&),
Chris Larsene3660592016-11-09 11:13:42 -0800206 const std::string& fmt,
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000207 int bias = 0,
208 int multiplier = 1) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700209 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800210 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Chris Larsendbce0d72015-09-17 13:34:00 -0700211
212 for (auto reg1 : reg1_registers) {
213 for (auto reg2 : reg2_registers) {
214 for (int64_t imm : imms) {
215 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700216 if (f != nullptr) {
217 (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
218 }
Chris Larsendbce0d72015-09-17 13:34:00 -0700219 std::string base = fmt;
220
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200221 std::string reg1_string = (this->*GetName1)(*reg1);
Chris Larsendbce0d72015-09-17 13:34:00 -0700222 size_t reg1_index;
223 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
224 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
225 }
226
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200227 std::string reg2_string = (this->*GetName2)(*reg2);
Chris Larsendbce0d72015-09-17 13:34:00 -0700228 size_t reg2_index;
229 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
230 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
231 }
232
233 size_t imm_index = base.find(IMM_TOKEN);
234 if (imm_index != std::string::npos) {
235 std::ostringstream sreg;
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000236 sreg << imm * multiplier + bias;
Chris Larsendbce0d72015-09-17 13:34:00 -0700237 std::string imm_string = sreg.str();
238 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
239 }
240
241 if (str.size() > 0) {
242 str += "\n";
243 }
244 str += base;
245 }
246 }
247 }
248 // Add a newline at the end.
249 str += "\n";
250 return str;
251 }
252
Chris Larsene3660592016-11-09 11:13:42 -0800253 template <typename Reg1, typename Reg2, typename Reg3, typename ImmType>
254 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType),
255 int imm_bits,
256 const std::vector<Reg1*> reg1_registers,
257 const std::vector<Reg2*> reg2_registers,
258 const std::vector<Reg3*> reg3_registers,
259 std::string (AssemblerTest::*GetName1)(const Reg1&),
260 std::string (AssemblerTest::*GetName2)(const Reg2&),
261 std::string (AssemblerTest::*GetName3)(const Reg3&),
262 std::string fmt,
263 int bias) {
264 std::string str;
265 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
266
267 for (auto reg1 : reg1_registers) {
268 for (auto reg2 : reg2_registers) {
269 for (auto reg3 : reg3_registers) {
270 for (int64_t imm : imms) {
271 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700272 if (f != nullptr) {
273 (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
274 }
Chris Larsene3660592016-11-09 11:13:42 -0800275 std::string base = fmt;
276
277 std::string reg1_string = (this->*GetName1)(*reg1);
278 size_t reg1_index;
279 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
280 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
281 }
282
283 std::string reg2_string = (this->*GetName2)(*reg2);
284 size_t reg2_index;
285 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
286 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
287 }
288
289 std::string reg3_string = (this->*GetName3)(*reg3);
290 size_t reg3_index;
291 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
292 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
293 }
294
295 size_t imm_index = base.find(IMM_TOKEN);
296 if (imm_index != std::string::npos) {
297 std::ostringstream sreg;
298 sreg << imm + bias;
299 std::string imm_string = sreg.str();
300 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
301 }
302
303 if (str.size() > 0) {
304 str += "\n";
305 }
306 str += base;
307 }
308 }
309 }
310 }
311 // Add a newline at the end.
312 str += "\n";
313 return str;
314 }
315
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800316 template <typename ImmType, typename Reg1, typename Reg2>
317 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
318 const std::vector<Reg1*> reg1_registers,
319 const std::vector<Reg2*> reg2_registers,
320 std::string (AssemblerTest::*GetName1)(const Reg1&),
321 std::string (AssemblerTest::*GetName2)(const Reg2&),
322 int imm_bits,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700323 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800324 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
325
326 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
327
328 std::string str;
329 for (auto reg1 : reg1_registers) {
330 for (auto reg2 : reg2_registers) {
331 for (int64_t imm : imms) {
332 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700333 if (f != nullptr) {
334 (assembler_.get()->*f)(new_imm, *reg1, *reg2);
335 }
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800336 std::string base = fmt;
337
338 std::string reg1_string = (this->*GetName1)(*reg1);
339 size_t reg1_index;
340 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
341 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
342 }
343
344 std::string reg2_string = (this->*GetName2)(*reg2);
345 size_t reg2_index;
346 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
347 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
348 }
349
350 size_t imm_index = base.find(IMM_TOKEN);
351 if (imm_index != std::string::npos) {
352 std::ostringstream sreg;
353 sreg << imm;
354 std::string imm_string = sreg.str();
355 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
356 }
357
358 if (str.size() > 0) {
359 str += "\n";
360 }
361 str += base;
362 }
363 }
364 }
365 // Add a newline at the end.
366 str += "\n";
367 return str;
368 }
369
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200370 template <typename RegType, typename ImmType>
371 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800372 int imm_bits,
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200373 const std::vector<RegType*> registers,
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800374 std::string (AssemblerTest::*GetName)(const RegType&),
Chris Larsene3660592016-11-09 11:13:42 -0800375 const std::string& fmt,
376 int bias) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200377 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800378 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200379
380 for (auto reg : registers) {
381 for (int64_t imm : imms) {
382 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700383 if (f != nullptr) {
384 (assembler_.get()->*f)(*reg, new_imm + bias);
385 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200386 std::string base = fmt;
387
388 std::string reg_string = (this->*GetName)(*reg);
389 size_t reg_index;
390 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
391 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
392 }
393
394 size_t imm_index = base.find(IMM_TOKEN);
395 if (imm_index != std::string::npos) {
396 std::ostringstream sreg;
Chris Larsene3660592016-11-09 11:13:42 -0800397 sreg << imm + bias;
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200398 std::string imm_string = sreg.str();
399 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
400 }
401
402 if (str.size() > 0) {
403 str += "\n";
404 }
405 str += base;
406 }
407 }
408 // Add a newline at the end.
409 str += "\n";
410 return str;
411 }
412
413 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800414 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
415 int imm_bits,
416 const std::string& fmt,
417 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200418 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
419 imm_bits,
420 GetRegisters(),
421 GetRegisters(),
422 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
423 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800424 fmt,
425 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200426 }
427
428 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800429 std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
430 int imm_bits,
431 const std::string& fmt,
432 int bias = 0) {
433 return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
434 imm_bits,
435 GetRegisters(),
436 GetRegisters(),
437 GetRegisters(),
438 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
439 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
440 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
441 fmt,
442 bias);
443 }
444
445 template <typename ImmType>
446 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200447 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
448 imm_bits,
449 GetRegisters(),
450 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800451 fmt,
452 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200453 }
454
455 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700456 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
457 int imm_bits,
Chris Larsene3660592016-11-09 11:13:42 -0800458 const std::string& fmt,
459 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200460 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
461 imm_bits,
462 GetFPRegisters(),
463 GetRegisters(),
464 &AssemblerTest::GetFPRegName,
465 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800466 fmt,
467 bias);
Chris Larsendbce0d72015-09-17 13:34:00 -0700468 }
469
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700470 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800471 return RepeatTemplatedRegisters<FPReg, FPReg>(f,
472 GetFPRegisters(),
473 GetFPRegisters(),
474 &AssemblerTest::GetFPRegName,
475 &AssemblerTest::GetFPRegName,
476 fmt);
477 }
478
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700479 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700480 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
481 GetFPRegisters(),
482 GetFPRegisters(),
483 GetFPRegisters(),
484 &AssemblerTest::GetFPRegName,
485 &AssemblerTest::GetFPRegName,
486 &AssemblerTest::GetFPRegName,
487 fmt);
488 }
489
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700490 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
Alexey Frunze674b9ee2016-09-20 14:54:15 -0700491 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
492 f,
493 GetFPRegisters(),
494 GetFPRegisters(),
495 GetRegisters(),
496 &AssemblerTest::GetFPRegName,
497 &AssemblerTest::GetFPRegName,
498 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
499 fmt);
500 }
501
Chris Larsendbce0d72015-09-17 13:34:00 -0700502 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
503 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700504 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400505 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
Chris Larsendbce0d72015-09-17 13:34:00 -0700506 GetFPRegisters(),
507 GetFPRegisters(),
508 &AssemblerTest::GetFPRegName,
509 &AssemblerTest::GetFPRegName,
510 imm_bytes,
511 fmt);
Mark Mendellfb8d2792015-03-31 22:16:59 -0400512 }
513
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800514 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700515 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
516 int imm_bits,
517 const std::string& fmt) {
Alexey Frunzea8aaf5a2016-06-27 14:48:20 -0700518 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
519 imm_bits,
520 GetFPRegisters(),
521 GetFPRegisters(),
522 &AssemblerTest::GetFPRegName,
523 &AssemblerTest::GetFPRegName,
524 fmt);
525 }
526
527 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700528 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
529 int imm_bits,
530 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800531 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
532 GetFPRegisters(),
533 GetFPRegisters(),
534 &AssemblerTest::GetFPRegName,
535 &AssemblerTest::GetFPRegName,
536 imm_bits,
537 fmt);
538 }
539
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700540 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800541 return RepeatTemplatedRegisters<FPReg, Reg>(f,
542 GetFPRegisters(),
543 GetRegisters(),
544 &AssemblerTest::GetFPRegName,
545 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
546 fmt);
547 }
548
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700549 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800550 return RepeatTemplatedRegisters<FPReg, Reg>(f,
551 GetFPRegisters(),
552 GetRegisters(),
553 &AssemblerTest::GetFPRegName,
554 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
555 fmt);
556 }
557
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700558 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800559 return RepeatTemplatedRegisters<Reg, FPReg>(f,
560 GetRegisters(),
561 GetFPRegisters(),
562 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
563 &AssemblerTest::GetFPRegName,
564 fmt);
565 }
566
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700567 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800568 return RepeatTemplatedRegisters<Reg, FPReg>(f,
569 GetRegisters(),
570 GetFPRegisters(),
571 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
572 &AssemblerTest::GetFPRegName,
573 fmt);
574 }
575
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700576 std::string RepeatI(void (Ass::*f)(const Imm&),
577 size_t imm_bytes,
578 const std::string& fmt,
Andreas Gampe851df202014-11-12 14:05:46 -0800579 bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700580 std::string str;
Andreas Gampe851df202014-11-12 14:05:46 -0800581 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800582
583 WarnOnCombinations(imms.size());
584
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700585 for (int64_t imm : imms) {
Ian Rogerscf7f1912014-10-22 22:06:39 -0700586 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700587 if (f != nullptr) {
588 (assembler_.get()->*f)(new_imm);
589 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700590 std::string base = fmt;
591
Andreas Gampe851df202014-11-12 14:05:46 -0800592 size_t imm_index = base.find(IMM_TOKEN);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700593 if (imm_index != std::string::npos) {
594 std::ostringstream sreg;
595 sreg << imm;
596 std::string imm_string = sreg.str();
Andreas Gampe851df202014-11-12 14:05:46 -0800597 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700598 }
599
600 if (str.size() > 0) {
601 str += "\n";
602 }
603 str += base;
604 }
605 // Add a newline at the end.
606 str += "\n";
607 return str;
608 }
609
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000610 std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
611 return RepeatTemplatedRegisters<VecReg, VecReg>(f,
612 GetVectorRegisters(),
613 GetVectorRegisters(),
614 &AssemblerTest::GetVecRegName,
615 &AssemblerTest::GetVecRegName,
616 fmt);
617 }
618
619 std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
620 return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
621 GetVectorRegisters(),
622 GetVectorRegisters(),
623 GetVectorRegisters(),
624 &AssemblerTest::GetVecRegName,
625 &AssemblerTest::GetVecRegName,
626 &AssemblerTest::GetVecRegName,
627 fmt);
628 }
629
630 std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
631 return RepeatTemplatedRegisters<VecReg, Reg>(
632 f,
633 GetVectorRegisters(),
634 GetRegisters(),
635 &AssemblerTest::GetVecRegName,
636 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
637 fmt);
638 }
639
640 template <typename ImmType>
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200641 std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
642 int imm_bits,
643 std::string fmt,
644 int bias = 0) {
645 return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
646 imm_bits,
647 GetVectorRegisters(),
648 &AssemblerTest::GetVecRegName,
649 fmt,
650 bias);
651 }
652
653 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000654 std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
655 int imm_bits,
656 const std::string& fmt,
657 int bias = 0,
658 int multiplier = 1) {
659 return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
660 f,
661 imm_bits,
662 GetVectorRegisters(),
663 GetRegisters(),
664 &AssemblerTest::GetVecRegName,
665 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
666 fmt,
667 bias,
668 multiplier);
669 }
670
671 template <typename ImmType>
Lena Djokic3309c012017-10-13 14:34:32 +0200672 std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
673 int imm_bits,
674 const std::string& fmt,
675 int bias = 0,
676 int multiplier = 1) {
677 return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
678 f,
679 imm_bits,
680 GetRegisters(),
681 GetVectorRegisters(),
682 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
683 &AssemblerTest::GetVecRegName,
684 fmt,
685 bias,
686 multiplier);
687 }
688
689 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000690 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
691 int imm_bits,
692 const std::string& fmt,
693 int bias = 0) {
694 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
695 imm_bits,
696 GetVectorRegisters(),
697 GetVectorRegisters(),
698 &AssemblerTest::GetVecRegName,
699 &AssemblerTest::GetVecRegName,
700 fmt,
701 bias);
702 }
703
Andreas Gampe851df202014-11-12 14:05:46 -0800704 // The following functions are public so that TestFn can use them...
705
Aart Bikcaa31e72017-09-14 17:08:50 -0700706 // Returns a vector of address used by any of the repeat methods
707 // involving an "A" (e.g. RepeatA).
708 virtual std::vector<Addr> GetAddresses() = 0;
709
710 // Returns a vector of registers used by any of the repeat methods
711 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800712 virtual std::vector<Reg*> GetRegisters() = 0;
713
Aart Bikcaa31e72017-09-14 17:08:50 -0700714 // Returns a vector of fp-registers used by any of the repeat methods
715 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800716 virtual std::vector<FPReg*> GetFPRegisters() {
717 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
718 UNREACHABLE();
719 }
720
Aart Bikcaa31e72017-09-14 17:08:50 -0700721 // Returns a vector of dedicated simd-registers used by any of the repeat
722 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000723 virtual std::vector<VecReg*> GetVectorRegisters() {
724 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
725 UNREACHABLE();
726 }
727
Andreas Gampe851df202014-11-12 14:05:46 -0800728 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
729 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
730 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
731 UNREACHABLE();
732 }
733
Chao-ying Fud23840d2015-04-07 16:03:04 -0700734 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
735 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
736 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
737 UNREACHABLE();
738 }
739
740 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
741 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
742 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
743 UNREACHABLE();
744 }
745
Calin Juravle9aec02f2014-11-18 23:06:35 +0000746 std::string GetRegisterName(const Reg& reg) {
747 return GetRegName<RegisterView::kUsePrimaryName>(reg);
748 }
749
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700750 protected:
Igor Murashkin2ffb7032017-11-08 13:35:21 -0800751 AssemblerTest() {}
Andreas Gampe851df202014-11-12 14:05:46 -0800752
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100753 void SetUp() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100754 AssemblerTestBase::SetUp();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100755 allocator_.reset(new ArenaAllocator(&pool_));
756 assembler_.reset(CreateAssembler(allocator_.get()));
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700757 SetUpHelpers();
758 }
759
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100760 void TearDown() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100761 AssemblerTestBase::TearDown();
Vladimir Marko93205e32016-04-13 11:59:46 +0100762 assembler_.reset();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100763 allocator_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700764 }
765
Chris Larsen3add9cb2016-04-14 14:01:33 -0700766 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100767 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
768 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700769 }
770
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700771 // Override this to set up any architecture-specific things, e.g., register vectors.
772 virtual void SetUpHelpers() {}
773
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700774 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800775 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700776 std::vector<int64_t> res;
777 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800778 if (!as_uint) {
779 res.push_back(-1);
780 } else {
781 res.push_back(0xFF);
782 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700783 res.push_back(0x12);
784 if (imm_bytes >= 2) {
785 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800786 if (!as_uint) {
787 res.push_back(-0x1234);
788 } else {
789 res.push_back(0xFFFF);
790 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700791 if (imm_bytes >= 4) {
792 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800793 if (!as_uint) {
794 res.push_back(-0x12345678);
795 } else {
796 res.push_back(0xFFFFFFFF);
797 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700798 if (imm_bytes >= 6) {
799 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800800 if (!as_uint) {
801 res.push_back(-0x123456789ABC);
802 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700803 if (imm_bytes >= 8) {
804 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800805 if (!as_uint) {
806 res.push_back(-0x123456789ABCDEF0);
807 } else {
808 res.push_back(0xFFFFFFFFFFFFFFFF);
809 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700810 }
811 }
812 }
813 }
814 return res;
815 }
816
Chris Larsendbce0d72015-09-17 13:34:00 -0700817 const int kMaxBitsExhaustiveTest = 8;
818
819 // Create a couple of immediate values up to the number of bits given.
820 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
821 CHECK_GT(imm_bits, 0);
822 CHECK_LE(imm_bits, 64);
823 std::vector<int64_t> res;
824
825 if (imm_bits <= kMaxBitsExhaustiveTest) {
826 if (as_uint) {
827 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
828 res.push_back(static_cast<int64_t>(i));
829 }
830 } else {
831 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
832 res.push_back(i);
833 }
834 }
835 } else {
836 if (as_uint) {
837 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
838 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
839 i++) {
840 res.push_back(static_cast<int64_t>(i));
841 }
842 for (int i = 0; i <= imm_bits; i++) {
843 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
844 ((MaxInt<uint64_t>(imm_bits) -
845 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
846 * i / imm_bits);
847 res.push_back(static_cast<int64_t>(j));
848 }
849 } else {
850 for (int i = 0; i <= imm_bits; i++) {
851 int64_t j = MinInt<int64_t>(imm_bits) +
852 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
853 MinInt<int64_t>(imm_bits))
854 * i) / imm_bits);
855 res.push_back(static_cast<int64_t>(j));
856 }
857 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
858 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
859 i++) {
860 res.push_back(static_cast<int64_t>(i));
861 }
862 for (int i = 0; i <= imm_bits; i++) {
863 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
864 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
865 * i / imm_bits);
866 res.push_back(static_cast<int64_t>(j));
867 }
868 }
869 }
870
871 return res;
872 }
873
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700874 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700875 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700876
Aart Bikcaa31e72017-09-14 17:08:50 -0700877 //
878 // Addresses repeats.
879 //
880
881 // Repeats over addresses provided by fixture.
882 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
883 return RepeatA(f, GetAddresses(), fmt);
884 }
885
886 // Variant that takes explicit vector of addresss
887 // (to test restricted addressing modes set).
888 std::string RepeatA(void (Ass::*f)(const Addr&),
889 const std::vector<Addr>& a,
890 const std::string& fmt) {
891 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
892 }
893
894 // Repeats over addresses and immediates provided by fixture.
895 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
896 size_t imm_bytes,
897 const std::string& fmt) {
898 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
899 }
900
901 // Variant that takes explicit vector of addresss
902 // (to test restricted addressing modes set).
903 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
904 size_t imm_bytes,
905 const std::vector<Addr>& a,
906 const std::string& fmt) {
907 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
908 }
909
910 // Repeats over registers and addresses provided by fixture.
911 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
912 return RepeatRA(f, GetAddresses(), fmt);
913 }
914
915 // Variant that takes explicit vector of addresss
916 // (to test restricted addressing modes set).
917 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
918 const std::vector<Addr>& a,
919 const std::string& fmt) {
920 return RepeatTemplatedRegMem<Reg, Addr>(
921 f,
922 GetRegisters(),
923 a,
924 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
925 &AssemblerTest::GetAddrName,
926 fmt);
927 }
928
Aart Bikf7754e82017-09-20 10:33:06 -0700929 // Repeats over secondary registers and addresses provided by fixture.
930 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
931 return RepeatrA(f, GetAddresses(), fmt);
932 }
933
934 // Variant that takes explicit vector of addresss
935 // (to test restricted addressing modes set).
936 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
937 const std::vector<Addr>& a,
938 const std::string& fmt) {
939 return RepeatTemplatedRegMem<Reg, Addr>(
940 f,
941 GetRegisters(),
942 a,
943 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
944 &AssemblerTest::GetAddrName,
945 fmt);
946 }
947
948 // Repeats over tertiary registers and addresses provided by fixture.
949 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
950 return RepeatwA(f, GetAddresses(), fmt);
951 }
952
953 // Variant that takes explicit vector of addresss
954 // (to test restricted addressing modes set).
955 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
956 const std::vector<Addr>& a,
957 const std::string& fmt) {
958 return RepeatTemplatedRegMem<Reg, Addr>(
959 f,
960 GetRegisters(),
961 a,
962 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
963 &AssemblerTest::GetAddrName,
964 fmt);
965 }
966
967 // Repeats over quaternary registers and addresses provided by fixture.
968 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
969 return RepeatbA(f, GetAddresses(), fmt);
970 }
971
972 // Variant that takes explicit vector of addresss
973 // (to test restricted addressing modes set).
974 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
975 const std::vector<Addr>& a,
976 const std::string& fmt) {
977 return RepeatTemplatedRegMem<Reg, Addr>(
978 f,
979 GetRegisters(),
980 a,
981 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
982 &AssemblerTest::GetAddrName,
983 fmt);
984 }
985
Aart Bikcaa31e72017-09-14 17:08:50 -0700986 // Repeats over fp-registers and addresses provided by fixture.
987 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
988 return RepeatFA(f, GetAddresses(), fmt);
989 }
990
991 // Variant that takes explicit vector of addresss
992 // (to test restricted addressing modes set).
993 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
994 const std::vector<Addr>& a,
995 const std::string& fmt) {
996 return RepeatTemplatedRegMem<FPReg, Addr>(
997 f,
998 GetFPRegisters(),
999 a,
1000 &AssemblerTest::GetFPRegName,
1001 &AssemblerTest::GetAddrName,
1002 fmt);
1003 }
1004
1005 // Repeats over addresses and registers provided by fixture.
1006 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1007 return RepeatAR(f, GetAddresses(), fmt);
1008 }
1009
1010 // Variant that takes explicit vector of addresss
1011 // (to test restricted addressing modes set).
1012 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1013 const std::vector<Addr>& a,
1014 const std::string& fmt) {
1015 return RepeatTemplatedMemReg<Addr, Reg>(
1016 f,
1017 a,
1018 GetRegisters(),
1019 &AssemblerTest::GetAddrName,
1020 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1021 fmt);
1022 }
1023
Aart Bikf7754e82017-09-20 10:33:06 -07001024 // Repeats over addresses and secondary registers provided by fixture.
1025 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1026 return RepeatAr(f, GetAddresses(), fmt);
1027 }
1028
1029 // Variant that takes explicit vector of addresss
1030 // (to test restricted addressing modes set).
1031 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1032 const std::vector<Addr>& a,
1033 const std::string& fmt) {
1034 return RepeatTemplatedMemReg<Addr, Reg>(
1035 f,
1036 a,
1037 GetRegisters(),
1038 &AssemblerTest::GetAddrName,
1039 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1040 fmt);
1041 }
1042
1043 // Repeats over addresses and tertiary registers provided by fixture.
1044 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1045 return RepeatAw(f, GetAddresses(), fmt);
1046 }
1047
1048 // Variant that takes explicit vector of addresss
1049 // (to test restricted addressing modes set).
1050 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1051 const std::vector<Addr>& a,
1052 const std::string& fmt) {
1053 return RepeatTemplatedMemReg<Addr, Reg>(
1054 f,
1055 a,
1056 GetRegisters(),
1057 &AssemblerTest::GetAddrName,
1058 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1059 fmt);
1060 }
1061
1062 // Repeats over addresses and quaternary registers provided by fixture.
1063 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1064 return RepeatAb(f, GetAddresses(), fmt);
1065 }
1066
1067 // Variant that takes explicit vector of addresss
1068 // (to test restricted addressing modes set).
1069 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1070 const std::vector<Addr>& a,
1071 const std::string& fmt) {
1072 return RepeatTemplatedMemReg<Addr, Reg>(
1073 f,
1074 a,
1075 GetRegisters(),
1076 &AssemblerTest::GetAddrName,
1077 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1078 fmt);
1079 }
1080
Aart Bikcaa31e72017-09-14 17:08:50 -07001081 // Repeats over addresses and fp-registers provided by fixture.
1082 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1083 return RepeatAF(f, GetAddresses(), fmt);
1084 }
1085
1086 // Variant that takes explicit vector of addresss
1087 // (to test restricted addressing modes set).
1088 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1089 const std::vector<Addr>& a,
1090 const std::string& fmt) {
1091 return RepeatTemplatedMemReg<Addr, FPReg>(
1092 f,
1093 a,
1094 GetFPRegisters(),
1095 &AssemblerTest::GetAddrName,
1096 &AssemblerTest::GetFPRegName,
1097 fmt);
1098 }
1099
1100 template <typename AddrType>
1101 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1102 const std::vector<AddrType> addresses,
1103 std::string (AssemblerTest::*GetAName)(const AddrType&),
1104 const std::string& fmt) {
1105 WarnOnCombinations(addresses.size());
1106 std::string str;
1107 for (auto addr : addresses) {
1108 if (f != nullptr) {
1109 (assembler_.get()->*f)(addr);
1110 }
1111 std::string base = fmt;
1112
1113 std::string addr_string = (this->*GetAName)(addr);
1114 size_t addr_index;
1115 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1116 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1117 }
1118
1119 if (str.size() > 0) {
1120 str += "\n";
1121 }
1122 str += base;
1123 }
1124 // Add a newline at the end.
1125 str += "\n";
1126 return str;
1127 }
1128
1129 template <typename AddrType>
1130 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1131 size_t imm_bytes,
1132 const std::vector<AddrType> addresses,
1133 std::string (AssemblerTest::*GetAName)(const AddrType&),
1134 const std::string& fmt) {
1135 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1136 WarnOnCombinations(addresses.size() * imms.size());
1137 std::string str;
1138 for (auto addr : addresses) {
1139 for (int64_t imm : imms) {
1140 Imm new_imm = CreateImmediate(imm);
1141 if (f != nullptr) {
1142 (assembler_.get()->*f)(addr, new_imm);
1143 }
1144 std::string base = fmt;
1145
1146 std::string addr_string = (this->*GetAName)(addr);
1147 size_t addr_index;
1148 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1149 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1150 }
1151
1152 size_t imm_index = base.find(IMM_TOKEN);
1153 if (imm_index != std::string::npos) {
1154 std::ostringstream sreg;
1155 sreg << imm;
1156 std::string imm_string = sreg.str();
1157 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1158 }
1159
1160 if (str.size() > 0) {
1161 str += "\n";
1162 }
1163 str += base;
1164 }
1165 }
1166 // Add a newline at the end.
1167 str += "\n";
1168 return str;
1169 }
1170
1171 template <typename RegType, typename AddrType>
1172 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1173 const std::vector<RegType*> registers,
1174 const std::vector<AddrType> addresses,
1175 std::string (AssemblerTest::*GetRName)(const RegType&),
1176 std::string (AssemblerTest::*GetAName)(const AddrType&),
1177 const std::string& fmt) {
1178 WarnOnCombinations(addresses.size() * registers.size());
1179 std::string str;
1180 for (auto reg : registers) {
1181 for (auto addr : addresses) {
1182 if (f != nullptr) {
1183 (assembler_.get()->*f)(*reg, addr);
1184 }
1185 std::string base = fmt;
1186
1187 std::string reg_string = (this->*GetRName)(*reg);
1188 size_t reg_index;
1189 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1190 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1191 }
1192
1193 std::string addr_string = (this->*GetAName)(addr);
1194 size_t addr_index;
1195 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1196 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1197 }
1198
1199 if (str.size() > 0) {
1200 str += "\n";
1201 }
1202 str += base;
1203 }
1204 }
1205 // Add a newline at the end.
1206 str += "\n";
1207 return str;
1208 }
1209
1210 template <typename AddrType, typename RegType>
1211 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1212 const std::vector<AddrType> addresses,
1213 const std::vector<RegType*> registers,
1214 std::string (AssemblerTest::*GetAName)(const AddrType&),
1215 std::string (AssemblerTest::*GetRName)(const RegType&),
1216 const std::string& fmt) {
1217 WarnOnCombinations(addresses.size() * registers.size());
1218 std::string str;
1219 for (auto addr : addresses) {
1220 for (auto reg : registers) {
1221 if (f != nullptr) {
1222 (assembler_.get()->*f)(addr, *reg);
1223 }
1224 std::string base = fmt;
1225
1226 std::string addr_string = (this->*GetAName)(addr);
1227 size_t addr_index;
1228 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1229 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1230 }
1231
1232 std::string reg_string = (this->*GetRName)(*reg);
1233 size_t reg_index;
1234 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1235 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1236 }
1237
1238 if (str.size() > 0) {
1239 str += "\n";
1240 }
1241 str += base;
1242 }
1243 }
1244 // Add a newline at the end.
1245 str += "\n";
1246 return str;
1247 }
1248
1249 //
1250 // Register repeats.
1251 //
1252
Andreas Gampe851df202014-11-12 14:05:46 -08001253 template <typename RegType>
1254 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1255 const std::vector<RegType*> registers,
1256 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001257 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001258 std::string str;
1259 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001260 if (f != nullptr) {
1261 (assembler_.get()->*f)(*reg);
1262 }
Andreas Gampe851df202014-11-12 14:05:46 -08001263 std::string base = fmt;
1264
1265 std::string reg_string = (this->*GetName)(*reg);
1266 size_t reg_index;
1267 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1268 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1269 }
1270
1271 if (str.size() > 0) {
1272 str += "\n";
1273 }
1274 str += base;
1275 }
1276 // Add a newline at the end.
1277 str += "\n";
1278 return str;
1279 }
1280
1281 template <typename Reg1, typename Reg2>
1282 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1283 const std::vector<Reg1*> reg1_registers,
1284 const std::vector<Reg2*> reg2_registers,
1285 std::string (AssemblerTest::*GetName1)(const Reg1&),
1286 std::string (AssemblerTest::*GetName2)(const Reg2&),
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +01001287 const std::string& fmt,
1288 const std::vector<std::pair<Reg1, Reg2>>* except = nullptr) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001289 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1290
Andreas Gampe851df202014-11-12 14:05:46 -08001291 std::string str;
1292 for (auto reg1 : reg1_registers) {
1293 for (auto reg2 : reg2_registers) {
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +01001294 // Check if this register pair is on the exception list. If so, skip it.
1295 if (except != nullptr) {
1296 const auto& pair = std::make_pair(*reg1, *reg2);
1297 if (std::find(except->begin(), except->end(), pair) != except->end()) {
1298 continue;
1299 }
1300 }
1301
Aart Bik5dafb3c2017-09-13 13:10:12 -07001302 if (f != nullptr) {
1303 (assembler_.get()->*f)(*reg1, *reg2);
1304 }
Andreas Gampe851df202014-11-12 14:05:46 -08001305 std::string base = fmt;
1306
1307 std::string reg1_string = (this->*GetName1)(*reg1);
1308 size_t reg1_index;
1309 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1310 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1311 }
1312
1313 std::string reg2_string = (this->*GetName2)(*reg2);
1314 size_t reg2_index;
1315 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1316 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1317 }
1318
1319 if (str.size() > 0) {
1320 str += "\n";
1321 }
1322 str += base;
1323 }
1324 }
1325 // Add a newline at the end.
1326 str += "\n";
1327 return str;
1328 }
1329
Chris Larsen51417632015-10-02 13:24:25 -07001330 template <typename Reg1, typename Reg2>
1331 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1332 const std::vector<Reg1*> reg1_registers,
1333 const std::vector<Reg2*> reg2_registers,
1334 std::string (AssemblerTest::*GetName1)(const Reg1&),
1335 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001336 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -07001337 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1338
1339 std::string str;
1340 for (auto reg1 : reg1_registers) {
1341 for (auto reg2 : reg2_registers) {
1342 if (reg1 == reg2) continue;
Aart Bik5dafb3c2017-09-13 13:10:12 -07001343 if (f != nullptr) {
1344 (assembler_.get()->*f)(*reg1, *reg2);
1345 }
Chris Larsen51417632015-10-02 13:24:25 -07001346 std::string base = fmt;
1347
1348 std::string reg1_string = (this->*GetName1)(*reg1);
1349 size_t reg1_index;
1350 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1351 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1352 }
1353
1354 std::string reg2_string = (this->*GetName2)(*reg2);
1355 size_t reg2_index;
1356 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1357 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1358 }
1359
1360 if (str.size() > 0) {
1361 str += "\n";
1362 }
1363 str += base;
1364 }
1365 }
1366 // Add a newline at the end.
1367 str += "\n";
1368 return str;
1369 }
1370
Chris Larsendbce0d72015-09-17 13:34:00 -07001371 template <typename Reg1, typename Reg2, typename Reg3>
1372 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1373 const std::vector<Reg1*> reg1_registers,
1374 const std::vector<Reg2*> reg2_registers,
1375 const std::vector<Reg3*> reg3_registers,
1376 std::string (AssemblerTest::*GetName1)(const Reg1&),
1377 std::string (AssemblerTest::*GetName2)(const Reg2&),
1378 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001379 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -07001380 std::string str;
1381 for (auto reg1 : reg1_registers) {
1382 for (auto reg2 : reg2_registers) {
1383 for (auto reg3 : reg3_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001384 if (f != nullptr) {
1385 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1386 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001387 std::string base = fmt;
1388
1389 std::string reg1_string = (this->*GetName1)(*reg1);
1390 size_t reg1_index;
1391 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1392 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1393 }
1394
1395 std::string reg2_string = (this->*GetName2)(*reg2);
1396 size_t reg2_index;
1397 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1398 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1399 }
1400
1401 std::string reg3_string = (this->*GetName3)(*reg3);
1402 size_t reg3_index;
1403 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
1404 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
1405 }
1406
1407 if (str.size() > 0) {
1408 str += "\n";
1409 }
1410 str += base;
1411 }
1412 }
1413 }
1414 // Add a newline at the end.
1415 str += "\n";
1416 return str;
1417 }
1418
Mark Mendellfb8d2792015-03-31 22:16:59 -04001419 template <typename Reg1, typename Reg2>
1420 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1421 const std::vector<Reg1*> reg1_registers,
1422 const std::vector<Reg2*> reg2_registers,
1423 std::string (AssemblerTest::*GetName1)(const Reg1&),
1424 std::string (AssemblerTest::*GetName2)(const Reg2&),
1425 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001426 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -04001427 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1428 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1429
1430 std::string str;
1431 for (auto reg1 : reg1_registers) {
1432 for (auto reg2 : reg2_registers) {
1433 for (int64_t imm : imms) {
1434 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001435 if (f != nullptr) {
1436 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1437 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001438 std::string base = fmt;
1439
1440 std::string reg1_string = (this->*GetName1)(*reg1);
1441 size_t reg1_index;
1442 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1443 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1444 }
1445
1446 std::string reg2_string = (this->*GetName2)(*reg2);
1447 size_t reg2_index;
1448 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1449 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1450 }
1451
1452 size_t imm_index = base.find(IMM_TOKEN);
1453 if (imm_index != std::string::npos) {
1454 std::ostringstream sreg;
1455 sreg << imm;
1456 std::string imm_string = sreg.str();
1457 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1458 }
1459
1460 if (str.size() > 0) {
1461 str += "\n";
1462 }
1463 str += base;
1464 }
1465 }
1466 }
1467 // Add a newline at the end.
1468 str += "\n";
1469 return str;
1470 }
1471
Aart Bikcaa31e72017-09-14 17:08:50 -07001472 std::string GetAddrName(const Addr& addr) {
1473 std::ostringstream saddr;
1474 saddr << addr;
1475 return saddr.str();
1476 }
1477
Andreas Gampe851df202014-11-12 14:05:46 -08001478 template <RegisterView kRegView>
1479 std::string GetRegName(const Reg& reg) {
1480 std::ostringstream sreg;
1481 switch (kRegView) {
1482 case RegisterView::kUsePrimaryName:
1483 sreg << reg;
1484 break;
1485
1486 case RegisterView::kUseSecondaryName:
1487 sreg << GetSecondaryRegisterName(reg);
1488 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -07001489
1490 case RegisterView::kUseTertiaryName:
1491 sreg << GetTertiaryRegisterName(reg);
1492 break;
1493
1494 case RegisterView::kUseQuaternaryName:
1495 sreg << GetQuaternaryRegisterName(reg);
1496 break;
Andreas Gampe851df202014-11-12 14:05:46 -08001497 }
1498 return sreg.str();
1499 }
1500
1501 std::string GetFPRegName(const FPReg& reg) {
1502 std::ostringstream sreg;
1503 sreg << reg;
1504 return sreg.str();
1505 }
1506
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001507 std::string GetVecRegName(const VecReg& reg) {
1508 std::ostringstream sreg;
1509 sreg << reg;
1510 return sreg.str();
1511 }
1512
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001513 void WarnOnCombinations(size_t count) {
1514 if (count > kWarnManyCombinationsThreshold) {
1515 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1516 }
1517 }
1518
Aart Bikcaa31e72017-09-14 17:08:50 -07001519 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001520 static constexpr const char* REG_TOKEN = "{reg}";
1521 static constexpr const char* REG1_TOKEN = "{reg1}";
1522 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001523 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001524 static constexpr const char* IMM_TOKEN = "{imm}";
1525
1526 private:
Andreas Gampe851df202014-11-12 14:05:46 -08001527 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001528 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1529 size_t imm_bytes,
1530 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001531 const std::vector<Reg*> registers = GetRegisters();
1532 std::string str;
1533 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001534
1535 WarnOnCombinations(registers.size() * imms.size());
1536
Andreas Gampe851df202014-11-12 14:05:46 -08001537 for (auto reg : registers) {
1538 for (int64_t imm : imms) {
1539 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001540 if (f != nullptr) {
1541 (assembler_.get()->*f)(*reg, new_imm);
1542 }
Andreas Gampe851df202014-11-12 14:05:46 -08001543 std::string base = fmt;
1544
1545 std::string reg_string = GetRegName<kRegView>(*reg);
1546 size_t reg_index;
1547 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1548 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1549 }
1550
1551 size_t imm_index = base.find(IMM_TOKEN);
1552 if (imm_index != std::string::npos) {
1553 std::ostringstream sreg;
1554 sreg << imm;
1555 std::string imm_string = sreg.str();
1556 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1557 }
1558
1559 if (str.size() > 0) {
1560 str += "\n";
1561 }
1562 str += base;
1563 }
1564 }
1565 // Add a newline at the end.
1566 str += "\n";
1567 return str;
1568 }
1569
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001570 // Override this to pad the code with NOPs to a certain size if needed.
1571 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1572 }
1573
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001574 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001575 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001576 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001577 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001578 MemoryRegion code(&(*data)[0], data->size());
1579 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001580 Pad(*data);
David Srbeckyd6e14e02020-07-01 13:19:17 +01001581 Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001582 }
1583
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001584 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001585
David Sehr3215fff2018-04-03 17:10:12 -07001586 MallocArenaPool pool_;
Vladimir Marko69d310e2017-10-09 14:12:23 +01001587 std::unique_ptr<ArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -07001588 std::unique_ptr<Ass> assembler_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001589
Andreas Gampe851df202014-11-12 14:05:46 -08001590 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001591};
1592
1593} // namespace art
1594
1595#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_