blob: 0cb8bbb2d54bad6e19848773bf6fcd4fe1676ef6 [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
29#include "assembler_test_base.h"
30#include "common_runtime_test.h" // For ScratchFile
Andreas Gampe5a4fa822014-03-31 16:50:12 -070031
32namespace art {
33
Andreas Gampe851df202014-11-12 14:05:46 -080034// Helper for a constexpr string length.
35constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
36 return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
37}
38
Andreas Gampe849cc5e2014-11-18 13:46:46 -080039enum class RegisterView { // private
40 kUsePrimaryName,
Chao-ying Fud23840d2015-04-07 16:03:04 -070041 kUseSecondaryName,
42 kUseTertiaryName,
43 kUseQuaternaryName,
Andreas Gampe849cc5e2014-11-18 13:46:46 -080044};
45
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +000046// For use in the template as the default type to get a nonvector registers version.
47struct NoVectorRegs {};
48
Aart Bikcaa31e72017-09-14 17:08:50 -070049template<typename Ass,
50 typename Addr,
51 typename Reg,
52 typename FPReg,
53 typename Imm,
54 typename VecReg = NoVectorRegs>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070055class AssemblerTest : public testing::Test {
56 public:
57 Ass* GetAssembler() {
58 return assembler_.get();
59 }
60
Andreas Gampe851df202014-11-12 14:05:46 -080061 typedef std::string (*TestFn)(AssemblerTest* assembler_test, Ass* assembler);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070062
Andreas Gampe2e965ac2016-11-03 17:24:15 -070063 void DriverFn(TestFn f, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070064 DriverWrapper(f(this, assembler_.get()), test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070065 }
66
67 // This driver assumes the assembler has already been called.
Andreas Gampe2e965ac2016-11-03 17:24:15 -070068 void DriverStr(const std::string& assembly_string, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070069 DriverWrapper(assembly_string, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070070 }
71
Aart Bikcaa31e72017-09-14 17:08:50 -070072 //
73 // Register repeats.
74 //
75
Andreas Gampe2e965ac2016-11-03 17:24:15 -070076 std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080077 return RepeatTemplatedRegister<Reg>(f,
78 GetRegisters(),
79 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
80 fmt);
81 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070082
Andreas Gampe2e965ac2016-11-03 17:24:15 -070083 std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080084 return RepeatTemplatedRegister<Reg>(f,
85 GetRegisters(),
86 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
87 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070088 }
89
Andreas Gampe2e965ac2016-11-03 17:24:15 -070090 std::string RepeatRR(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080091 return RepeatTemplatedRegisters<Reg, Reg>(f,
92 GetRegisters(),
93 GetRegisters(),
94 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
95 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
96 fmt);
97 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070098
Andreas Gampe2e965ac2016-11-03 17:24:15 -070099 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -0700100 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
101 GetRegisters(),
102 GetRegisters(),
103 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
104 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
105 fmt);
106 }
107
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700108 std::string Repeatrr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800109 return RepeatTemplatedRegisters<Reg, Reg>(f,
110 GetRegisters(),
111 GetRegisters(),
112 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
113 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
114 fmt);
115 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700116
Aart Bikf7754e82017-09-20 10:33:06 -0700117 std::string Repeatww(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
118 return RepeatTemplatedRegisters<Reg, Reg>(f,
119 GetRegisters(),
120 GetRegisters(),
121 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
122 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
123 fmt);
124 }
125
126 std::string Repeatbb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
127 return RepeatTemplatedRegisters<Reg, Reg>(f,
128 GetRegisters(),
129 GetRegisters(),
130 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
131 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
132 fmt);
133 }
134
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700135 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700136 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
137 GetRegisters(),
138 GetRegisters(),
139 GetRegisters(),
140 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
141 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
142 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
143 fmt);
144 }
145
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700146 std::string Repeatrb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700147 return RepeatTemplatedRegisters<Reg, Reg>(f,
148 GetRegisters(),
149 GetRegisters(),
150 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
151 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
152 fmt);
153 }
154
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700155 std::string RepeatRr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800156 return RepeatTemplatedRegisters<Reg, Reg>(f,
157 GetRegisters(),
158 GetRegisters(),
159 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
160 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
161 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700162 }
163
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700164 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800165 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700166 }
167
Aart Bikf7754e82017-09-20 10:33:06 -0700168 std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800169 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
170 }
171
Aart Bikf7754e82017-09-20 10:33:06 -0700172 std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
173 return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
174 }
175
176 std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
177 return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
178 }
179
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200180 template <typename Reg1, typename Reg2, typename ImmType>
181 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
182 int imm_bits,
183 const std::vector<Reg1*> reg1_registers,
184 const std::vector<Reg2*> reg2_registers,
185 std::string (AssemblerTest::*GetName1)(const Reg1&),
186 std::string (AssemblerTest::*GetName2)(const Reg2&),
Chris Larsene3660592016-11-09 11:13:42 -0800187 const std::string& fmt,
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000188 int bias = 0,
189 int multiplier = 1) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700190 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800191 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Chris Larsendbce0d72015-09-17 13:34:00 -0700192
193 for (auto reg1 : reg1_registers) {
194 for (auto reg2 : reg2_registers) {
195 for (int64_t imm : imms) {
196 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700197 if (f != nullptr) {
198 (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
199 }
Chris Larsendbce0d72015-09-17 13:34:00 -0700200 std::string base = fmt;
201
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200202 std::string reg1_string = (this->*GetName1)(*reg1);
Chris Larsendbce0d72015-09-17 13:34:00 -0700203 size_t reg1_index;
204 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
205 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
206 }
207
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200208 std::string reg2_string = (this->*GetName2)(*reg2);
Chris Larsendbce0d72015-09-17 13:34:00 -0700209 size_t reg2_index;
210 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
211 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
212 }
213
214 size_t imm_index = base.find(IMM_TOKEN);
215 if (imm_index != std::string::npos) {
216 std::ostringstream sreg;
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000217 sreg << imm * multiplier + bias;
Chris Larsendbce0d72015-09-17 13:34:00 -0700218 std::string imm_string = sreg.str();
219 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
220 }
221
222 if (str.size() > 0) {
223 str += "\n";
224 }
225 str += base;
226 }
227 }
228 }
229 // Add a newline at the end.
230 str += "\n";
231 return str;
232 }
233
Chris Larsene3660592016-11-09 11:13:42 -0800234 template <typename Reg1, typename Reg2, typename Reg3, typename ImmType>
235 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType),
236 int imm_bits,
237 const std::vector<Reg1*> reg1_registers,
238 const std::vector<Reg2*> reg2_registers,
239 const std::vector<Reg3*> reg3_registers,
240 std::string (AssemblerTest::*GetName1)(const Reg1&),
241 std::string (AssemblerTest::*GetName2)(const Reg2&),
242 std::string (AssemblerTest::*GetName3)(const Reg3&),
243 std::string fmt,
244 int bias) {
245 std::string str;
246 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
247
248 for (auto reg1 : reg1_registers) {
249 for (auto reg2 : reg2_registers) {
250 for (auto reg3 : reg3_registers) {
251 for (int64_t imm : imms) {
252 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700253 if (f != nullptr) {
254 (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
255 }
Chris Larsene3660592016-11-09 11:13:42 -0800256 std::string base = fmt;
257
258 std::string reg1_string = (this->*GetName1)(*reg1);
259 size_t reg1_index;
260 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
261 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
262 }
263
264 std::string reg2_string = (this->*GetName2)(*reg2);
265 size_t reg2_index;
266 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
267 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
268 }
269
270 std::string reg3_string = (this->*GetName3)(*reg3);
271 size_t reg3_index;
272 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
273 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
274 }
275
276 size_t imm_index = base.find(IMM_TOKEN);
277 if (imm_index != std::string::npos) {
278 std::ostringstream sreg;
279 sreg << imm + bias;
280 std::string imm_string = sreg.str();
281 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
282 }
283
284 if (str.size() > 0) {
285 str += "\n";
286 }
287 str += base;
288 }
289 }
290 }
291 }
292 // Add a newline at the end.
293 str += "\n";
294 return str;
295 }
296
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800297 template <typename ImmType, typename Reg1, typename Reg2>
298 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
299 const std::vector<Reg1*> reg1_registers,
300 const std::vector<Reg2*> reg2_registers,
301 std::string (AssemblerTest::*GetName1)(const Reg1&),
302 std::string (AssemblerTest::*GetName2)(const Reg2&),
303 int imm_bits,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700304 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800305 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
306
307 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
308
309 std::string str;
310 for (auto reg1 : reg1_registers) {
311 for (auto reg2 : reg2_registers) {
312 for (int64_t imm : imms) {
313 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700314 if (f != nullptr) {
315 (assembler_.get()->*f)(new_imm, *reg1, *reg2);
316 }
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800317 std::string base = fmt;
318
319 std::string reg1_string = (this->*GetName1)(*reg1);
320 size_t reg1_index;
321 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
322 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
323 }
324
325 std::string reg2_string = (this->*GetName2)(*reg2);
326 size_t reg2_index;
327 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
328 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
329 }
330
331 size_t imm_index = base.find(IMM_TOKEN);
332 if (imm_index != std::string::npos) {
333 std::ostringstream sreg;
334 sreg << imm;
335 std::string imm_string = sreg.str();
336 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
337 }
338
339 if (str.size() > 0) {
340 str += "\n";
341 }
342 str += base;
343 }
344 }
345 }
346 // Add a newline at the end.
347 str += "\n";
348 return str;
349 }
350
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200351 template <typename RegType, typename ImmType>
352 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800353 int imm_bits,
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200354 const std::vector<RegType*> registers,
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800355 std::string (AssemblerTest::*GetName)(const RegType&),
Chris Larsene3660592016-11-09 11:13:42 -0800356 const std::string& fmt,
357 int bias) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200358 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800359 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200360
361 for (auto reg : registers) {
362 for (int64_t imm : imms) {
363 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700364 if (f != nullptr) {
365 (assembler_.get()->*f)(*reg, new_imm + bias);
366 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200367 std::string base = fmt;
368
369 std::string reg_string = (this->*GetName)(*reg);
370 size_t reg_index;
371 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
372 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
373 }
374
375 size_t imm_index = base.find(IMM_TOKEN);
376 if (imm_index != std::string::npos) {
377 std::ostringstream sreg;
Chris Larsene3660592016-11-09 11:13:42 -0800378 sreg << imm + bias;
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200379 std::string imm_string = sreg.str();
380 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
381 }
382
383 if (str.size() > 0) {
384 str += "\n";
385 }
386 str += base;
387 }
388 }
389 // Add a newline at the end.
390 str += "\n";
391 return str;
392 }
393
394 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800395 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
396 int imm_bits,
397 const std::string& fmt,
398 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200399 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
400 imm_bits,
401 GetRegisters(),
402 GetRegisters(),
403 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
404 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800405 fmt,
406 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200407 }
408
409 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800410 std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
411 int imm_bits,
412 const std::string& fmt,
413 int bias = 0) {
414 return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
415 imm_bits,
416 GetRegisters(),
417 GetRegisters(),
418 GetRegisters(),
419 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
420 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
421 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
422 fmt,
423 bias);
424 }
425
426 template <typename ImmType>
427 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200428 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
429 imm_bits,
430 GetRegisters(),
431 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800432 fmt,
433 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200434 }
435
436 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700437 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
438 int imm_bits,
Chris Larsene3660592016-11-09 11:13:42 -0800439 const std::string& fmt,
440 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200441 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
442 imm_bits,
443 GetFPRegisters(),
444 GetRegisters(),
445 &AssemblerTest::GetFPRegName,
446 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800447 fmt,
448 bias);
Chris Larsendbce0d72015-09-17 13:34:00 -0700449 }
450
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700451 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800452 return RepeatTemplatedRegisters<FPReg, FPReg>(f,
453 GetFPRegisters(),
454 GetFPRegisters(),
455 &AssemblerTest::GetFPRegName,
456 &AssemblerTest::GetFPRegName,
457 fmt);
458 }
459
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700460 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700461 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
462 GetFPRegisters(),
463 GetFPRegisters(),
464 GetFPRegisters(),
465 &AssemblerTest::GetFPRegName,
466 &AssemblerTest::GetFPRegName,
467 &AssemblerTest::GetFPRegName,
468 fmt);
469 }
470
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700471 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
Alexey Frunze674b9ee2016-09-20 14:54:15 -0700472 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
473 f,
474 GetFPRegisters(),
475 GetFPRegisters(),
476 GetRegisters(),
477 &AssemblerTest::GetFPRegName,
478 &AssemblerTest::GetFPRegName,
479 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
480 fmt);
481 }
482
Chris Larsendbce0d72015-09-17 13:34:00 -0700483 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
484 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700485 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400486 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
Chris Larsendbce0d72015-09-17 13:34:00 -0700487 GetFPRegisters(),
488 GetFPRegisters(),
489 &AssemblerTest::GetFPRegName,
490 &AssemblerTest::GetFPRegName,
491 imm_bytes,
492 fmt);
Mark Mendellfb8d2792015-03-31 22:16:59 -0400493 }
494
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800495 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700496 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
497 int imm_bits,
498 const std::string& fmt) {
Alexey Frunzea8aaf5a2016-06-27 14:48:20 -0700499 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
500 imm_bits,
501 GetFPRegisters(),
502 GetFPRegisters(),
503 &AssemblerTest::GetFPRegName,
504 &AssemblerTest::GetFPRegName,
505 fmt);
506 }
507
508 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700509 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
510 int imm_bits,
511 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800512 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
513 GetFPRegisters(),
514 GetFPRegisters(),
515 &AssemblerTest::GetFPRegName,
516 &AssemblerTest::GetFPRegName,
517 imm_bits,
518 fmt);
519 }
520
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700521 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800522 return RepeatTemplatedRegisters<FPReg, Reg>(f,
523 GetFPRegisters(),
524 GetRegisters(),
525 &AssemblerTest::GetFPRegName,
526 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
527 fmt);
528 }
529
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700530 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800531 return RepeatTemplatedRegisters<FPReg, Reg>(f,
532 GetFPRegisters(),
533 GetRegisters(),
534 &AssemblerTest::GetFPRegName,
535 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
536 fmt);
537 }
538
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700539 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800540 return RepeatTemplatedRegisters<Reg, FPReg>(f,
541 GetRegisters(),
542 GetFPRegisters(),
543 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
544 &AssemblerTest::GetFPRegName,
545 fmt);
546 }
547
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700548 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800549 return RepeatTemplatedRegisters<Reg, FPReg>(f,
550 GetRegisters(),
551 GetFPRegisters(),
552 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
553 &AssemblerTest::GetFPRegName,
554 fmt);
555 }
556
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700557 std::string RepeatI(void (Ass::*f)(const Imm&),
558 size_t imm_bytes,
559 const std::string& fmt,
Andreas Gampe851df202014-11-12 14:05:46 -0800560 bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700561 std::string str;
Andreas Gampe851df202014-11-12 14:05:46 -0800562 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800563
564 WarnOnCombinations(imms.size());
565
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700566 for (int64_t imm : imms) {
Ian Rogerscf7f1912014-10-22 22:06:39 -0700567 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700568 if (f != nullptr) {
569 (assembler_.get()->*f)(new_imm);
570 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700571 std::string base = fmt;
572
Andreas Gampe851df202014-11-12 14:05:46 -0800573 size_t imm_index = base.find(IMM_TOKEN);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700574 if (imm_index != std::string::npos) {
575 std::ostringstream sreg;
576 sreg << imm;
577 std::string imm_string = sreg.str();
Andreas Gampe851df202014-11-12 14:05:46 -0800578 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700579 }
580
581 if (str.size() > 0) {
582 str += "\n";
583 }
584 str += base;
585 }
586 // Add a newline at the end.
587 str += "\n";
588 return str;
589 }
590
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000591 std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
592 return RepeatTemplatedRegisters<VecReg, VecReg>(f,
593 GetVectorRegisters(),
594 GetVectorRegisters(),
595 &AssemblerTest::GetVecRegName,
596 &AssemblerTest::GetVecRegName,
597 fmt);
598 }
599
600 std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
601 return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
602 GetVectorRegisters(),
603 GetVectorRegisters(),
604 GetVectorRegisters(),
605 &AssemblerTest::GetVecRegName,
606 &AssemblerTest::GetVecRegName,
607 &AssemblerTest::GetVecRegName,
608 fmt);
609 }
610
611 std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
612 return RepeatTemplatedRegisters<VecReg, Reg>(
613 f,
614 GetVectorRegisters(),
615 GetRegisters(),
616 &AssemblerTest::GetVecRegName,
617 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
618 fmt);
619 }
620
621 template <typename ImmType>
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200622 std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
623 int imm_bits,
624 std::string fmt,
625 int bias = 0) {
626 return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
627 imm_bits,
628 GetVectorRegisters(),
629 &AssemblerTest::GetVecRegName,
630 fmt,
631 bias);
632 }
633
634 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000635 std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
636 int imm_bits,
637 const std::string& fmt,
638 int bias = 0,
639 int multiplier = 1) {
640 return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
641 f,
642 imm_bits,
643 GetVectorRegisters(),
644 GetRegisters(),
645 &AssemblerTest::GetVecRegName,
646 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
647 fmt,
648 bias,
649 multiplier);
650 }
651
652 template <typename ImmType>
Lena Djokic3309c012017-10-13 14:34:32 +0200653 std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
654 int imm_bits,
655 const std::string& fmt,
656 int bias = 0,
657 int multiplier = 1) {
658 return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
659 f,
660 imm_bits,
661 GetRegisters(),
662 GetVectorRegisters(),
663 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
664 &AssemblerTest::GetVecRegName,
665 fmt,
666 bias,
667 multiplier);
668 }
669
670 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000671 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
672 int imm_bits,
673 const std::string& fmt,
674 int bias = 0) {
675 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
676 imm_bits,
677 GetVectorRegisters(),
678 GetVectorRegisters(),
679 &AssemblerTest::GetVecRegName,
680 &AssemblerTest::GetVecRegName,
681 fmt,
682 bias);
683 }
684
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700685 // This is intended to be run as a test.
686 bool CheckTools() {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700687 return test_helper_->CheckTools();
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700688 }
689
Andreas Gampe851df202014-11-12 14:05:46 -0800690 // The following functions are public so that TestFn can use them...
691
Aart Bikcaa31e72017-09-14 17:08:50 -0700692 // Returns a vector of address used by any of the repeat methods
693 // involving an "A" (e.g. RepeatA).
694 virtual std::vector<Addr> GetAddresses() = 0;
695
696 // Returns a vector of registers used by any of the repeat methods
697 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800698 virtual std::vector<Reg*> GetRegisters() = 0;
699
Aart Bikcaa31e72017-09-14 17:08:50 -0700700 // Returns a vector of fp-registers used by any of the repeat methods
701 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800702 virtual std::vector<FPReg*> GetFPRegisters() {
703 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
704 UNREACHABLE();
705 }
706
Aart Bikcaa31e72017-09-14 17:08:50 -0700707 // Returns a vector of dedicated simd-registers used by any of the repeat
708 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000709 virtual std::vector<VecReg*> GetVectorRegisters() {
710 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
711 UNREACHABLE();
712 }
713
Andreas Gampe851df202014-11-12 14:05:46 -0800714 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
715 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
716 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
717 UNREACHABLE();
718 }
719
Chao-ying Fud23840d2015-04-07 16:03:04 -0700720 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
721 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
722 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
723 UNREACHABLE();
724 }
725
726 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
727 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
728 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
729 UNREACHABLE();
730 }
731
Calin Juravle9aec02f2014-11-18 23:06:35 +0000732 std::string GetRegisterName(const Reg& reg) {
733 return GetRegName<RegisterView::kUsePrimaryName>(reg);
734 }
735
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700736 protected:
Igor Murashkin2ffb7032017-11-08 13:35:21 -0800737 AssemblerTest() {}
Andreas Gampe851df202014-11-12 14:05:46 -0800738
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700739 void SetUp() OVERRIDE {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100740 allocator_.reset(new ArenaAllocator(&pool_));
741 assembler_.reset(CreateAssembler(allocator_.get()));
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700742 test_helper_.reset(
743 new AssemblerTestInfrastructure(GetArchitectureString(),
744 GetAssemblerCmdName(),
745 GetAssemblerParameters(),
746 GetObjdumpCmdName(),
747 GetObjdumpParameters(),
748 GetDisassembleCmdName(),
749 GetDisassembleParameters(),
750 GetAssemblyHeader()));
Andreas Gampeb40c6a72014-05-02 14:25:12 -0700751
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700752 SetUpHelpers();
753 }
754
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700755 void TearDown() OVERRIDE {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700756 test_helper_.reset(); // Clean up the helper.
Vladimir Marko93205e32016-04-13 11:59:46 +0100757 assembler_.reset();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100758 allocator_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700759 }
760
Chris Larsen3add9cb2016-04-14 14:01:33 -0700761 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100762 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
763 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700764 }
765
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700766 // Override this to set up any architecture-specific things, e.g., register vectors.
767 virtual void SetUpHelpers() {}
768
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700769 // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
770 virtual std::string GetArchitectureString() = 0;
771
772 // Get the name of the assembler, e.g., "as" by default.
773 virtual std::string GetAssemblerCmdName() {
774 return "as";
775 }
776
777 // Switches to the assembler command. Default none.
778 virtual std::string GetAssemblerParameters() {
779 return "";
780 }
781
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700782 // Get the name of the objdump, e.g., "objdump" by default.
783 virtual std::string GetObjdumpCmdName() {
784 return "objdump";
785 }
786
787 // Switches to the objdump command. Default is " -h".
788 virtual std::string GetObjdumpParameters() {
789 return " -h";
790 }
791
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700792 // Get the name of the objdump, e.g., "objdump" by default.
793 virtual std::string GetDisassembleCmdName() {
794 return "objdump";
795 }
796
797 // Switches to the objdump command. As it's a binary, one needs to push the architecture and
798 // such to objdump, so it's architecture-specific and there is no default.
799 virtual std::string GetDisassembleParameters() = 0;
800
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700801 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800802 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700803 std::vector<int64_t> res;
804 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800805 if (!as_uint) {
806 res.push_back(-1);
807 } else {
808 res.push_back(0xFF);
809 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700810 res.push_back(0x12);
811 if (imm_bytes >= 2) {
812 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800813 if (!as_uint) {
814 res.push_back(-0x1234);
815 } else {
816 res.push_back(0xFFFF);
817 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700818 if (imm_bytes >= 4) {
819 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800820 if (!as_uint) {
821 res.push_back(-0x12345678);
822 } else {
823 res.push_back(0xFFFFFFFF);
824 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700825 if (imm_bytes >= 6) {
826 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800827 if (!as_uint) {
828 res.push_back(-0x123456789ABC);
829 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700830 if (imm_bytes >= 8) {
831 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800832 if (!as_uint) {
833 res.push_back(-0x123456789ABCDEF0);
834 } else {
835 res.push_back(0xFFFFFFFFFFFFFFFF);
836 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700837 }
838 }
839 }
840 }
841 return res;
842 }
843
Chris Larsendbce0d72015-09-17 13:34:00 -0700844 const int kMaxBitsExhaustiveTest = 8;
845
846 // Create a couple of immediate values up to the number of bits given.
847 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
848 CHECK_GT(imm_bits, 0);
849 CHECK_LE(imm_bits, 64);
850 std::vector<int64_t> res;
851
852 if (imm_bits <= kMaxBitsExhaustiveTest) {
853 if (as_uint) {
854 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
855 res.push_back(static_cast<int64_t>(i));
856 }
857 } else {
858 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
859 res.push_back(i);
860 }
861 }
862 } else {
863 if (as_uint) {
864 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
865 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
866 i++) {
867 res.push_back(static_cast<int64_t>(i));
868 }
869 for (int i = 0; i <= imm_bits; i++) {
870 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
871 ((MaxInt<uint64_t>(imm_bits) -
872 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
873 * i / imm_bits);
874 res.push_back(static_cast<int64_t>(j));
875 }
876 } else {
877 for (int i = 0; i <= imm_bits; i++) {
878 int64_t j = MinInt<int64_t>(imm_bits) +
879 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
880 MinInt<int64_t>(imm_bits))
881 * i) / imm_bits);
882 res.push_back(static_cast<int64_t>(j));
883 }
884 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
885 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
886 i++) {
887 res.push_back(static_cast<int64_t>(i));
888 }
889 for (int i = 0; i <= imm_bits; i++) {
890 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
891 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
892 * i / imm_bits);
893 res.push_back(static_cast<int64_t>(j));
894 }
895 }
896 }
897
898 return res;
899 }
900
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700901 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700902 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700903
Aart Bikcaa31e72017-09-14 17:08:50 -0700904 //
905 // Addresses repeats.
906 //
907
908 // Repeats over addresses provided by fixture.
909 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
910 return RepeatA(f, GetAddresses(), fmt);
911 }
912
913 // Variant that takes explicit vector of addresss
914 // (to test restricted addressing modes set).
915 std::string RepeatA(void (Ass::*f)(const Addr&),
916 const std::vector<Addr>& a,
917 const std::string& fmt) {
918 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
919 }
920
921 // Repeats over addresses and immediates provided by fixture.
922 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
923 size_t imm_bytes,
924 const std::string& fmt) {
925 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
926 }
927
928 // Variant that takes explicit vector of addresss
929 // (to test restricted addressing modes set).
930 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
931 size_t imm_bytes,
932 const std::vector<Addr>& a,
933 const std::string& fmt) {
934 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
935 }
936
937 // Repeats over registers and addresses provided by fixture.
938 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
939 return RepeatRA(f, GetAddresses(), fmt);
940 }
941
942 // Variant that takes explicit vector of addresss
943 // (to test restricted addressing modes set).
944 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
945 const std::vector<Addr>& a,
946 const std::string& fmt) {
947 return RepeatTemplatedRegMem<Reg, Addr>(
948 f,
949 GetRegisters(),
950 a,
951 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
952 &AssemblerTest::GetAddrName,
953 fmt);
954 }
955
Aart Bikf7754e82017-09-20 10:33:06 -0700956 // Repeats over secondary registers and addresses provided by fixture.
957 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
958 return RepeatrA(f, GetAddresses(), fmt);
959 }
960
961 // Variant that takes explicit vector of addresss
962 // (to test restricted addressing modes set).
963 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
964 const std::vector<Addr>& a,
965 const std::string& fmt) {
966 return RepeatTemplatedRegMem<Reg, Addr>(
967 f,
968 GetRegisters(),
969 a,
970 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
971 &AssemblerTest::GetAddrName,
972 fmt);
973 }
974
975 // Repeats over tertiary registers and addresses provided by fixture.
976 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
977 return RepeatwA(f, GetAddresses(), fmt);
978 }
979
980 // Variant that takes explicit vector of addresss
981 // (to test restricted addressing modes set).
982 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
983 const std::vector<Addr>& a,
984 const std::string& fmt) {
985 return RepeatTemplatedRegMem<Reg, Addr>(
986 f,
987 GetRegisters(),
988 a,
989 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
990 &AssemblerTest::GetAddrName,
991 fmt);
992 }
993
994 // Repeats over quaternary registers and addresses provided by fixture.
995 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
996 return RepeatbA(f, GetAddresses(), fmt);
997 }
998
999 // Variant that takes explicit vector of addresss
1000 // (to test restricted addressing modes set).
1001 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
1002 const std::vector<Addr>& a,
1003 const std::string& fmt) {
1004 return RepeatTemplatedRegMem<Reg, Addr>(
1005 f,
1006 GetRegisters(),
1007 a,
1008 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1009 &AssemblerTest::GetAddrName,
1010 fmt);
1011 }
1012
Aart Bikcaa31e72017-09-14 17:08:50 -07001013 // Repeats over fp-registers and addresses provided by fixture.
1014 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
1015 return RepeatFA(f, GetAddresses(), fmt);
1016 }
1017
1018 // Variant that takes explicit vector of addresss
1019 // (to test restricted addressing modes set).
1020 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1021 const std::vector<Addr>& a,
1022 const std::string& fmt) {
1023 return RepeatTemplatedRegMem<FPReg, Addr>(
1024 f,
1025 GetFPRegisters(),
1026 a,
1027 &AssemblerTest::GetFPRegName,
1028 &AssemblerTest::GetAddrName,
1029 fmt);
1030 }
1031
1032 // Repeats over addresses and registers provided by fixture.
1033 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1034 return RepeatAR(f, GetAddresses(), fmt);
1035 }
1036
1037 // Variant that takes explicit vector of addresss
1038 // (to test restricted addressing modes set).
1039 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1040 const std::vector<Addr>& a,
1041 const std::string& fmt) {
1042 return RepeatTemplatedMemReg<Addr, Reg>(
1043 f,
1044 a,
1045 GetRegisters(),
1046 &AssemblerTest::GetAddrName,
1047 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1048 fmt);
1049 }
1050
Aart Bikf7754e82017-09-20 10:33:06 -07001051 // Repeats over addresses and secondary registers provided by fixture.
1052 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1053 return RepeatAr(f, GetAddresses(), fmt);
1054 }
1055
1056 // Variant that takes explicit vector of addresss
1057 // (to test restricted addressing modes set).
1058 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1059 const std::vector<Addr>& a,
1060 const std::string& fmt) {
1061 return RepeatTemplatedMemReg<Addr, Reg>(
1062 f,
1063 a,
1064 GetRegisters(),
1065 &AssemblerTest::GetAddrName,
1066 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1067 fmt);
1068 }
1069
1070 // Repeats over addresses and tertiary registers provided by fixture.
1071 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1072 return RepeatAw(f, GetAddresses(), fmt);
1073 }
1074
1075 // Variant that takes explicit vector of addresss
1076 // (to test restricted addressing modes set).
1077 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1078 const std::vector<Addr>& a,
1079 const std::string& fmt) {
1080 return RepeatTemplatedMemReg<Addr, Reg>(
1081 f,
1082 a,
1083 GetRegisters(),
1084 &AssemblerTest::GetAddrName,
1085 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1086 fmt);
1087 }
1088
1089 // Repeats over addresses and quaternary registers provided by fixture.
1090 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1091 return RepeatAb(f, GetAddresses(), fmt);
1092 }
1093
1094 // Variant that takes explicit vector of addresss
1095 // (to test restricted addressing modes set).
1096 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1097 const std::vector<Addr>& a,
1098 const std::string& fmt) {
1099 return RepeatTemplatedMemReg<Addr, Reg>(
1100 f,
1101 a,
1102 GetRegisters(),
1103 &AssemblerTest::GetAddrName,
1104 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1105 fmt);
1106 }
1107
Aart Bikcaa31e72017-09-14 17:08:50 -07001108 // Repeats over addresses and fp-registers provided by fixture.
1109 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1110 return RepeatAF(f, GetAddresses(), fmt);
1111 }
1112
1113 // Variant that takes explicit vector of addresss
1114 // (to test restricted addressing modes set).
1115 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1116 const std::vector<Addr>& a,
1117 const std::string& fmt) {
1118 return RepeatTemplatedMemReg<Addr, FPReg>(
1119 f,
1120 a,
1121 GetFPRegisters(),
1122 &AssemblerTest::GetAddrName,
1123 &AssemblerTest::GetFPRegName,
1124 fmt);
1125 }
1126
1127 template <typename AddrType>
1128 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1129 const std::vector<AddrType> addresses,
1130 std::string (AssemblerTest::*GetAName)(const AddrType&),
1131 const std::string& fmt) {
1132 WarnOnCombinations(addresses.size());
1133 std::string str;
1134 for (auto addr : addresses) {
1135 if (f != nullptr) {
1136 (assembler_.get()->*f)(addr);
1137 }
1138 std::string base = fmt;
1139
1140 std::string addr_string = (this->*GetAName)(addr);
1141 size_t addr_index;
1142 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1143 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1144 }
1145
1146 if (str.size() > 0) {
1147 str += "\n";
1148 }
1149 str += base;
1150 }
1151 // Add a newline at the end.
1152 str += "\n";
1153 return str;
1154 }
1155
1156 template <typename AddrType>
1157 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1158 size_t imm_bytes,
1159 const std::vector<AddrType> addresses,
1160 std::string (AssemblerTest::*GetAName)(const AddrType&),
1161 const std::string& fmt) {
1162 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1163 WarnOnCombinations(addresses.size() * imms.size());
1164 std::string str;
1165 for (auto addr : addresses) {
1166 for (int64_t imm : imms) {
1167 Imm new_imm = CreateImmediate(imm);
1168 if (f != nullptr) {
1169 (assembler_.get()->*f)(addr, new_imm);
1170 }
1171 std::string base = fmt;
1172
1173 std::string addr_string = (this->*GetAName)(addr);
1174 size_t addr_index;
1175 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1176 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1177 }
1178
1179 size_t imm_index = base.find(IMM_TOKEN);
1180 if (imm_index != std::string::npos) {
1181 std::ostringstream sreg;
1182 sreg << imm;
1183 std::string imm_string = sreg.str();
1184 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1185 }
1186
1187 if (str.size() > 0) {
1188 str += "\n";
1189 }
1190 str += base;
1191 }
1192 }
1193 // Add a newline at the end.
1194 str += "\n";
1195 return str;
1196 }
1197
1198 template <typename RegType, typename AddrType>
1199 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1200 const std::vector<RegType*> registers,
1201 const std::vector<AddrType> addresses,
1202 std::string (AssemblerTest::*GetRName)(const RegType&),
1203 std::string (AssemblerTest::*GetAName)(const AddrType&),
1204 const std::string& fmt) {
1205 WarnOnCombinations(addresses.size() * registers.size());
1206 std::string str;
1207 for (auto reg : registers) {
1208 for (auto addr : addresses) {
1209 if (f != nullptr) {
1210 (assembler_.get()->*f)(*reg, addr);
1211 }
1212 std::string base = fmt;
1213
1214 std::string reg_string = (this->*GetRName)(*reg);
1215 size_t reg_index;
1216 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1217 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1218 }
1219
1220 std::string addr_string = (this->*GetAName)(addr);
1221 size_t addr_index;
1222 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1223 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1224 }
1225
1226 if (str.size() > 0) {
1227 str += "\n";
1228 }
1229 str += base;
1230 }
1231 }
1232 // Add a newline at the end.
1233 str += "\n";
1234 return str;
1235 }
1236
1237 template <typename AddrType, typename RegType>
1238 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1239 const std::vector<AddrType> addresses,
1240 const std::vector<RegType*> registers,
1241 std::string (AssemblerTest::*GetAName)(const AddrType&),
1242 std::string (AssemblerTest::*GetRName)(const RegType&),
1243 const std::string& fmt) {
1244 WarnOnCombinations(addresses.size() * registers.size());
1245 std::string str;
1246 for (auto addr : addresses) {
1247 for (auto reg : registers) {
1248 if (f != nullptr) {
1249 (assembler_.get()->*f)(addr, *reg);
1250 }
1251 std::string base = fmt;
1252
1253 std::string addr_string = (this->*GetAName)(addr);
1254 size_t addr_index;
1255 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1256 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1257 }
1258
1259 std::string reg_string = (this->*GetRName)(*reg);
1260 size_t reg_index;
1261 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1262 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1263 }
1264
1265 if (str.size() > 0) {
1266 str += "\n";
1267 }
1268 str += base;
1269 }
1270 }
1271 // Add a newline at the end.
1272 str += "\n";
1273 return str;
1274 }
1275
1276 //
1277 // Register repeats.
1278 //
1279
Andreas Gampe851df202014-11-12 14:05:46 -08001280 template <typename RegType>
1281 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1282 const std::vector<RegType*> registers,
1283 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001284 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001285 std::string str;
1286 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001287 if (f != nullptr) {
1288 (assembler_.get()->*f)(*reg);
1289 }
Andreas Gampe851df202014-11-12 14:05:46 -08001290 std::string base = fmt;
1291
1292 std::string reg_string = (this->*GetName)(*reg);
1293 size_t reg_index;
1294 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1295 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1296 }
1297
1298 if (str.size() > 0) {
1299 str += "\n";
1300 }
1301 str += base;
1302 }
1303 // Add a newline at the end.
1304 str += "\n";
1305 return str;
1306 }
1307
1308 template <typename Reg1, typename Reg2>
1309 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1310 const std::vector<Reg1*> reg1_registers,
1311 const std::vector<Reg2*> reg2_registers,
1312 std::string (AssemblerTest::*GetName1)(const Reg1&),
1313 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001314 const std::string& fmt) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001315 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1316
Andreas Gampe851df202014-11-12 14:05:46 -08001317 std::string str;
1318 for (auto reg1 : reg1_registers) {
1319 for (auto reg2 : reg2_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001320 if (f != nullptr) {
1321 (assembler_.get()->*f)(*reg1, *reg2);
1322 }
Andreas Gampe851df202014-11-12 14:05:46 -08001323 std::string base = fmt;
1324
1325 std::string reg1_string = (this->*GetName1)(*reg1);
1326 size_t reg1_index;
1327 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1328 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1329 }
1330
1331 std::string reg2_string = (this->*GetName2)(*reg2);
1332 size_t reg2_index;
1333 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1334 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1335 }
1336
1337 if (str.size() > 0) {
1338 str += "\n";
1339 }
1340 str += base;
1341 }
1342 }
1343 // Add a newline at the end.
1344 str += "\n";
1345 return str;
1346 }
1347
Chris Larsen51417632015-10-02 13:24:25 -07001348 template <typename Reg1, typename Reg2>
1349 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1350 const std::vector<Reg1*> reg1_registers,
1351 const std::vector<Reg2*> reg2_registers,
1352 std::string (AssemblerTest::*GetName1)(const Reg1&),
1353 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001354 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -07001355 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1356
1357 std::string str;
1358 for (auto reg1 : reg1_registers) {
1359 for (auto reg2 : reg2_registers) {
1360 if (reg1 == reg2) continue;
Aart Bik5dafb3c2017-09-13 13:10:12 -07001361 if (f != nullptr) {
1362 (assembler_.get()->*f)(*reg1, *reg2);
1363 }
Chris Larsen51417632015-10-02 13:24:25 -07001364 std::string base = fmt;
1365
1366 std::string reg1_string = (this->*GetName1)(*reg1);
1367 size_t reg1_index;
1368 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1369 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1370 }
1371
1372 std::string reg2_string = (this->*GetName2)(*reg2);
1373 size_t reg2_index;
1374 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1375 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1376 }
1377
1378 if (str.size() > 0) {
1379 str += "\n";
1380 }
1381 str += base;
1382 }
1383 }
1384 // Add a newline at the end.
1385 str += "\n";
1386 return str;
1387 }
1388
Chris Larsendbce0d72015-09-17 13:34:00 -07001389 template <typename Reg1, typename Reg2, typename Reg3>
1390 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1391 const std::vector<Reg1*> reg1_registers,
1392 const std::vector<Reg2*> reg2_registers,
1393 const std::vector<Reg3*> reg3_registers,
1394 std::string (AssemblerTest::*GetName1)(const Reg1&),
1395 std::string (AssemblerTest::*GetName2)(const Reg2&),
1396 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001397 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -07001398 std::string str;
1399 for (auto reg1 : reg1_registers) {
1400 for (auto reg2 : reg2_registers) {
1401 for (auto reg3 : reg3_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001402 if (f != nullptr) {
1403 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1404 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001405 std::string base = fmt;
1406
1407 std::string reg1_string = (this->*GetName1)(*reg1);
1408 size_t reg1_index;
1409 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1410 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1411 }
1412
1413 std::string reg2_string = (this->*GetName2)(*reg2);
1414 size_t reg2_index;
1415 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1416 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1417 }
1418
1419 std::string reg3_string = (this->*GetName3)(*reg3);
1420 size_t reg3_index;
1421 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
1422 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
1423 }
1424
1425 if (str.size() > 0) {
1426 str += "\n";
1427 }
1428 str += base;
1429 }
1430 }
1431 }
1432 // Add a newline at the end.
1433 str += "\n";
1434 return str;
1435 }
1436
Mark Mendellfb8d2792015-03-31 22:16:59 -04001437 template <typename Reg1, typename Reg2>
1438 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1439 const std::vector<Reg1*> reg1_registers,
1440 const std::vector<Reg2*> reg2_registers,
1441 std::string (AssemblerTest::*GetName1)(const Reg1&),
1442 std::string (AssemblerTest::*GetName2)(const Reg2&),
1443 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001444 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -04001445 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1446 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1447
1448 std::string str;
1449 for (auto reg1 : reg1_registers) {
1450 for (auto reg2 : reg2_registers) {
1451 for (int64_t imm : imms) {
1452 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001453 if (f != nullptr) {
1454 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1455 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001456 std::string base = fmt;
1457
1458 std::string reg1_string = (this->*GetName1)(*reg1);
1459 size_t reg1_index;
1460 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1461 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1462 }
1463
1464 std::string reg2_string = (this->*GetName2)(*reg2);
1465 size_t reg2_index;
1466 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1467 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1468 }
1469
1470 size_t imm_index = base.find(IMM_TOKEN);
1471 if (imm_index != std::string::npos) {
1472 std::ostringstream sreg;
1473 sreg << imm;
1474 std::string imm_string = sreg.str();
1475 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1476 }
1477
1478 if (str.size() > 0) {
1479 str += "\n";
1480 }
1481 str += base;
1482 }
1483 }
1484 }
1485 // Add a newline at the end.
1486 str += "\n";
1487 return str;
1488 }
1489
Aart Bikcaa31e72017-09-14 17:08:50 -07001490 std::string GetAddrName(const Addr& addr) {
1491 std::ostringstream saddr;
1492 saddr << addr;
1493 return saddr.str();
1494 }
1495
Andreas Gampe851df202014-11-12 14:05:46 -08001496 template <RegisterView kRegView>
1497 std::string GetRegName(const Reg& reg) {
1498 std::ostringstream sreg;
1499 switch (kRegView) {
1500 case RegisterView::kUsePrimaryName:
1501 sreg << reg;
1502 break;
1503
1504 case RegisterView::kUseSecondaryName:
1505 sreg << GetSecondaryRegisterName(reg);
1506 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -07001507
1508 case RegisterView::kUseTertiaryName:
1509 sreg << GetTertiaryRegisterName(reg);
1510 break;
1511
1512 case RegisterView::kUseQuaternaryName:
1513 sreg << GetQuaternaryRegisterName(reg);
1514 break;
Andreas Gampe851df202014-11-12 14:05:46 -08001515 }
1516 return sreg.str();
1517 }
1518
1519 std::string GetFPRegName(const FPReg& reg) {
1520 std::ostringstream sreg;
1521 sreg << reg;
1522 return sreg.str();
1523 }
1524
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001525 std::string GetVecRegName(const VecReg& reg) {
1526 std::ostringstream sreg;
1527 sreg << reg;
1528 return sreg.str();
1529 }
1530
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001531 // If the assembly file needs a header, return it in a sub-class.
1532 virtual const char* GetAssemblyHeader() {
1533 return nullptr;
1534 }
1535
1536 void WarnOnCombinations(size_t count) {
1537 if (count > kWarnManyCombinationsThreshold) {
1538 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1539 }
1540 }
1541
Aart Bikcaa31e72017-09-14 17:08:50 -07001542 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001543 static constexpr const char* REG_TOKEN = "{reg}";
1544 static constexpr const char* REG1_TOKEN = "{reg1}";
1545 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001546 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001547 static constexpr const char* IMM_TOKEN = "{imm}";
1548
1549 private:
Andreas Gampe851df202014-11-12 14:05:46 -08001550 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001551 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1552 size_t imm_bytes,
1553 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001554 const std::vector<Reg*> registers = GetRegisters();
1555 std::string str;
1556 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001557
1558 WarnOnCombinations(registers.size() * imms.size());
1559
Andreas Gampe851df202014-11-12 14:05:46 -08001560 for (auto reg : registers) {
1561 for (int64_t imm : imms) {
1562 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001563 if (f != nullptr) {
1564 (assembler_.get()->*f)(*reg, new_imm);
1565 }
Andreas Gampe851df202014-11-12 14:05:46 -08001566 std::string base = fmt;
1567
1568 std::string reg_string = GetRegName<kRegView>(*reg);
1569 size_t reg_index;
1570 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1571 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1572 }
1573
1574 size_t imm_index = base.find(IMM_TOKEN);
1575 if (imm_index != std::string::npos) {
1576 std::ostringstream sreg;
1577 sreg << imm;
1578 std::string imm_string = sreg.str();
1579 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1580 }
1581
1582 if (str.size() > 0) {
1583 str += "\n";
1584 }
1585 str += base;
1586 }
1587 }
1588 // Add a newline at the end.
1589 str += "\n";
1590 return str;
1591 }
1592
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001593 // Override this to pad the code with NOPs to a certain size if needed.
1594 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1595 }
1596
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001597 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001598 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001599 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001600 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001601 MemoryRegion code(&(*data)[0], data->size());
1602 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001603 Pad(*data);
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001604 test_helper_->Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001605 }
1606
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001607 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001608
Vladimir Marko93205e32016-04-13 11:59:46 +01001609 ArenaPool pool_;
Vladimir Marko69d310e2017-10-09 14:12:23 +01001610 std::unique_ptr<ArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -07001611 std::unique_ptr<Ass> assembler_;
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001612 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001613
Andreas Gampe851df202014-11-12 14:05:46 -08001614 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001615};
1616
1617} // namespace art
1618
1619#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_