blob: 11a9b91600c394e38ca61adeb213e75fc764fe7b [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>
653 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
654 int imm_bits,
655 const std::string& fmt,
656 int bias = 0) {
657 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
658 imm_bits,
659 GetVectorRegisters(),
660 GetVectorRegisters(),
661 &AssemblerTest::GetVecRegName,
662 &AssemblerTest::GetVecRegName,
663 fmt,
664 bias);
665 }
666
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700667 // This is intended to be run as a test.
668 bool CheckTools() {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700669 return test_helper_->CheckTools();
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700670 }
671
Andreas Gampe851df202014-11-12 14:05:46 -0800672 // The following functions are public so that TestFn can use them...
673
Aart Bikcaa31e72017-09-14 17:08:50 -0700674 // Returns a vector of address used by any of the repeat methods
675 // involving an "A" (e.g. RepeatA).
676 virtual std::vector<Addr> GetAddresses() = 0;
677
678 // Returns a vector of registers used by any of the repeat methods
679 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800680 virtual std::vector<Reg*> GetRegisters() = 0;
681
Aart Bikcaa31e72017-09-14 17:08:50 -0700682 // Returns a vector of fp-registers used by any of the repeat methods
683 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800684 virtual std::vector<FPReg*> GetFPRegisters() {
685 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
686 UNREACHABLE();
687 }
688
Aart Bikcaa31e72017-09-14 17:08:50 -0700689 // Returns a vector of dedicated simd-registers used by any of the repeat
690 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000691 virtual std::vector<VecReg*> GetVectorRegisters() {
692 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
693 UNREACHABLE();
694 }
695
Andreas Gampe851df202014-11-12 14:05:46 -0800696 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
697 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
698 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
699 UNREACHABLE();
700 }
701
Chao-ying Fud23840d2015-04-07 16:03:04 -0700702 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
703 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
704 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
705 UNREACHABLE();
706 }
707
708 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
709 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
710 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
711 UNREACHABLE();
712 }
713
Calin Juravle9aec02f2014-11-18 23:06:35 +0000714 std::string GetRegisterName(const Reg& reg) {
715 return GetRegName<RegisterView::kUsePrimaryName>(reg);
716 }
717
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700718 protected:
Andreas Gampe851df202014-11-12 14:05:46 -0800719 explicit AssemblerTest() {}
720
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700721 void SetUp() OVERRIDE {
Vladimir Marko93205e32016-04-13 11:59:46 +0100722 arena_.reset(new ArenaAllocator(&pool_));
Chris Larsen3add9cb2016-04-14 14:01:33 -0700723 assembler_.reset(CreateAssembler(arena_.get()));
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700724 test_helper_.reset(
725 new AssemblerTestInfrastructure(GetArchitectureString(),
726 GetAssemblerCmdName(),
727 GetAssemblerParameters(),
728 GetObjdumpCmdName(),
729 GetObjdumpParameters(),
730 GetDisassembleCmdName(),
731 GetDisassembleParameters(),
732 GetAssemblyHeader()));
Andreas Gampeb40c6a72014-05-02 14:25:12 -0700733
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700734 SetUpHelpers();
735 }
736
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700737 void TearDown() OVERRIDE {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700738 test_helper_.reset(); // Clean up the helper.
Vladimir Marko93205e32016-04-13 11:59:46 +0100739 assembler_.reset();
740 arena_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700741 }
742
Chris Larsen3add9cb2016-04-14 14:01:33 -0700743 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100744 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
745 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700746 }
747
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700748 // Override this to set up any architecture-specific things, e.g., register vectors.
749 virtual void SetUpHelpers() {}
750
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700751 // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
752 virtual std::string GetArchitectureString() = 0;
753
754 // Get the name of the assembler, e.g., "as" by default.
755 virtual std::string GetAssemblerCmdName() {
756 return "as";
757 }
758
759 // Switches to the assembler command. Default none.
760 virtual std::string GetAssemblerParameters() {
761 return "";
762 }
763
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700764 // Get the name of the objdump, e.g., "objdump" by default.
765 virtual std::string GetObjdumpCmdName() {
766 return "objdump";
767 }
768
769 // Switches to the objdump command. Default is " -h".
770 virtual std::string GetObjdumpParameters() {
771 return " -h";
772 }
773
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700774 // Get the name of the objdump, e.g., "objdump" by default.
775 virtual std::string GetDisassembleCmdName() {
776 return "objdump";
777 }
778
779 // Switches to the objdump command. As it's a binary, one needs to push the architecture and
780 // such to objdump, so it's architecture-specific and there is no default.
781 virtual std::string GetDisassembleParameters() = 0;
782
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700783 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800784 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700785 std::vector<int64_t> res;
786 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800787 if (!as_uint) {
788 res.push_back(-1);
789 } else {
790 res.push_back(0xFF);
791 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700792 res.push_back(0x12);
793 if (imm_bytes >= 2) {
794 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800795 if (!as_uint) {
796 res.push_back(-0x1234);
797 } else {
798 res.push_back(0xFFFF);
799 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700800 if (imm_bytes >= 4) {
801 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800802 if (!as_uint) {
803 res.push_back(-0x12345678);
804 } else {
805 res.push_back(0xFFFFFFFF);
806 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700807 if (imm_bytes >= 6) {
808 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800809 if (!as_uint) {
810 res.push_back(-0x123456789ABC);
811 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700812 if (imm_bytes >= 8) {
813 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800814 if (!as_uint) {
815 res.push_back(-0x123456789ABCDEF0);
816 } else {
817 res.push_back(0xFFFFFFFFFFFFFFFF);
818 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700819 }
820 }
821 }
822 }
823 return res;
824 }
825
Chris Larsendbce0d72015-09-17 13:34:00 -0700826 const int kMaxBitsExhaustiveTest = 8;
827
828 // Create a couple of immediate values up to the number of bits given.
829 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
830 CHECK_GT(imm_bits, 0);
831 CHECK_LE(imm_bits, 64);
832 std::vector<int64_t> res;
833
834 if (imm_bits <= kMaxBitsExhaustiveTest) {
835 if (as_uint) {
836 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
837 res.push_back(static_cast<int64_t>(i));
838 }
839 } else {
840 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
841 res.push_back(i);
842 }
843 }
844 } else {
845 if (as_uint) {
846 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
847 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
848 i++) {
849 res.push_back(static_cast<int64_t>(i));
850 }
851 for (int i = 0; i <= imm_bits; i++) {
852 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
853 ((MaxInt<uint64_t>(imm_bits) -
854 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
855 * i / imm_bits);
856 res.push_back(static_cast<int64_t>(j));
857 }
858 } else {
859 for (int i = 0; i <= imm_bits; i++) {
860 int64_t j = MinInt<int64_t>(imm_bits) +
861 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
862 MinInt<int64_t>(imm_bits))
863 * i) / imm_bits);
864 res.push_back(static_cast<int64_t>(j));
865 }
866 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
867 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
868 i++) {
869 res.push_back(static_cast<int64_t>(i));
870 }
871 for (int i = 0; i <= imm_bits; i++) {
872 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
873 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
874 * i / imm_bits);
875 res.push_back(static_cast<int64_t>(j));
876 }
877 }
878 }
879
880 return res;
881 }
882
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700883 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700884 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700885
Aart Bikcaa31e72017-09-14 17:08:50 -0700886 //
887 // Addresses repeats.
888 //
889
890 // Repeats over addresses provided by fixture.
891 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
892 return RepeatA(f, GetAddresses(), fmt);
893 }
894
895 // Variant that takes explicit vector of addresss
896 // (to test restricted addressing modes set).
897 std::string RepeatA(void (Ass::*f)(const Addr&),
898 const std::vector<Addr>& a,
899 const std::string& fmt) {
900 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
901 }
902
903 // Repeats over addresses and immediates provided by fixture.
904 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
905 size_t imm_bytes,
906 const std::string& fmt) {
907 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
908 }
909
910 // Variant that takes explicit vector of addresss
911 // (to test restricted addressing modes set).
912 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
913 size_t imm_bytes,
914 const std::vector<Addr>& a,
915 const std::string& fmt) {
916 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
917 }
918
919 // Repeats over registers and addresses provided by fixture.
920 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
921 return RepeatRA(f, GetAddresses(), fmt);
922 }
923
924 // Variant that takes explicit vector of addresss
925 // (to test restricted addressing modes set).
926 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
927 const std::vector<Addr>& a,
928 const std::string& fmt) {
929 return RepeatTemplatedRegMem<Reg, Addr>(
930 f,
931 GetRegisters(),
932 a,
933 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
934 &AssemblerTest::GetAddrName,
935 fmt);
936 }
937
Aart Bikf7754e82017-09-20 10:33:06 -0700938 // Repeats over secondary registers and addresses provided by fixture.
939 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
940 return RepeatrA(f, GetAddresses(), fmt);
941 }
942
943 // Variant that takes explicit vector of addresss
944 // (to test restricted addressing modes set).
945 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
946 const std::vector<Addr>& a,
947 const std::string& fmt) {
948 return RepeatTemplatedRegMem<Reg, Addr>(
949 f,
950 GetRegisters(),
951 a,
952 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
953 &AssemblerTest::GetAddrName,
954 fmt);
955 }
956
957 // Repeats over tertiary registers and addresses provided by fixture.
958 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
959 return RepeatwA(f, GetAddresses(), fmt);
960 }
961
962 // Variant that takes explicit vector of addresss
963 // (to test restricted addressing modes set).
964 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
965 const std::vector<Addr>& a,
966 const std::string& fmt) {
967 return RepeatTemplatedRegMem<Reg, Addr>(
968 f,
969 GetRegisters(),
970 a,
971 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
972 &AssemblerTest::GetAddrName,
973 fmt);
974 }
975
976 // Repeats over quaternary registers and addresses provided by fixture.
977 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
978 return RepeatbA(f, GetAddresses(), fmt);
979 }
980
981 // Variant that takes explicit vector of addresss
982 // (to test restricted addressing modes set).
983 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
984 const std::vector<Addr>& a,
985 const std::string& fmt) {
986 return RepeatTemplatedRegMem<Reg, Addr>(
987 f,
988 GetRegisters(),
989 a,
990 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
991 &AssemblerTest::GetAddrName,
992 fmt);
993 }
994
Aart Bikcaa31e72017-09-14 17:08:50 -0700995 // Repeats over fp-registers and addresses provided by fixture.
996 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
997 return RepeatFA(f, GetAddresses(), fmt);
998 }
999
1000 // Variant that takes explicit vector of addresss
1001 // (to test restricted addressing modes set).
1002 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1003 const std::vector<Addr>& a,
1004 const std::string& fmt) {
1005 return RepeatTemplatedRegMem<FPReg, Addr>(
1006 f,
1007 GetFPRegisters(),
1008 a,
1009 &AssemblerTest::GetFPRegName,
1010 &AssemblerTest::GetAddrName,
1011 fmt);
1012 }
1013
1014 // Repeats over addresses and registers provided by fixture.
1015 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1016 return RepeatAR(f, GetAddresses(), fmt);
1017 }
1018
1019 // Variant that takes explicit vector of addresss
1020 // (to test restricted addressing modes set).
1021 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1022 const std::vector<Addr>& a,
1023 const std::string& fmt) {
1024 return RepeatTemplatedMemReg<Addr, Reg>(
1025 f,
1026 a,
1027 GetRegisters(),
1028 &AssemblerTest::GetAddrName,
1029 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1030 fmt);
1031 }
1032
Aart Bikf7754e82017-09-20 10:33:06 -07001033 // Repeats over addresses and secondary registers provided by fixture.
1034 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1035 return RepeatAr(f, GetAddresses(), fmt);
1036 }
1037
1038 // Variant that takes explicit vector of addresss
1039 // (to test restricted addressing modes set).
1040 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1041 const std::vector<Addr>& a,
1042 const std::string& fmt) {
1043 return RepeatTemplatedMemReg<Addr, Reg>(
1044 f,
1045 a,
1046 GetRegisters(),
1047 &AssemblerTest::GetAddrName,
1048 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1049 fmt);
1050 }
1051
1052 // Repeats over addresses and tertiary registers provided by fixture.
1053 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1054 return RepeatAw(f, GetAddresses(), fmt);
1055 }
1056
1057 // Variant that takes explicit vector of addresss
1058 // (to test restricted addressing modes set).
1059 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1060 const std::vector<Addr>& a,
1061 const std::string& fmt) {
1062 return RepeatTemplatedMemReg<Addr, Reg>(
1063 f,
1064 a,
1065 GetRegisters(),
1066 &AssemblerTest::GetAddrName,
1067 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1068 fmt);
1069 }
1070
1071 // Repeats over addresses and quaternary registers provided by fixture.
1072 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1073 return RepeatAb(f, GetAddresses(), fmt);
1074 }
1075
1076 // Variant that takes explicit vector of addresss
1077 // (to test restricted addressing modes set).
1078 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1079 const std::vector<Addr>& a,
1080 const std::string& fmt) {
1081 return RepeatTemplatedMemReg<Addr, Reg>(
1082 f,
1083 a,
1084 GetRegisters(),
1085 &AssemblerTest::GetAddrName,
1086 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1087 fmt);
1088 }
1089
Aart Bikcaa31e72017-09-14 17:08:50 -07001090 // Repeats over addresses and fp-registers provided by fixture.
1091 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1092 return RepeatAF(f, GetAddresses(), fmt);
1093 }
1094
1095 // Variant that takes explicit vector of addresss
1096 // (to test restricted addressing modes set).
1097 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1098 const std::vector<Addr>& a,
1099 const std::string& fmt) {
1100 return RepeatTemplatedMemReg<Addr, FPReg>(
1101 f,
1102 a,
1103 GetFPRegisters(),
1104 &AssemblerTest::GetAddrName,
1105 &AssemblerTest::GetFPRegName,
1106 fmt);
1107 }
1108
1109 template <typename AddrType>
1110 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1111 const std::vector<AddrType> addresses,
1112 std::string (AssemblerTest::*GetAName)(const AddrType&),
1113 const std::string& fmt) {
1114 WarnOnCombinations(addresses.size());
1115 std::string str;
1116 for (auto addr : addresses) {
1117 if (f != nullptr) {
1118 (assembler_.get()->*f)(addr);
1119 }
1120 std::string base = fmt;
1121
1122 std::string addr_string = (this->*GetAName)(addr);
1123 size_t addr_index;
1124 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1125 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1126 }
1127
1128 if (str.size() > 0) {
1129 str += "\n";
1130 }
1131 str += base;
1132 }
1133 // Add a newline at the end.
1134 str += "\n";
1135 return str;
1136 }
1137
1138 template <typename AddrType>
1139 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1140 size_t imm_bytes,
1141 const std::vector<AddrType> addresses,
1142 std::string (AssemblerTest::*GetAName)(const AddrType&),
1143 const std::string& fmt) {
1144 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1145 WarnOnCombinations(addresses.size() * imms.size());
1146 std::string str;
1147 for (auto addr : addresses) {
1148 for (int64_t imm : imms) {
1149 Imm new_imm = CreateImmediate(imm);
1150 if (f != nullptr) {
1151 (assembler_.get()->*f)(addr, new_imm);
1152 }
1153 std::string base = fmt;
1154
1155 std::string addr_string = (this->*GetAName)(addr);
1156 size_t addr_index;
1157 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1158 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1159 }
1160
1161 size_t imm_index = base.find(IMM_TOKEN);
1162 if (imm_index != std::string::npos) {
1163 std::ostringstream sreg;
1164 sreg << imm;
1165 std::string imm_string = sreg.str();
1166 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1167 }
1168
1169 if (str.size() > 0) {
1170 str += "\n";
1171 }
1172 str += base;
1173 }
1174 }
1175 // Add a newline at the end.
1176 str += "\n";
1177 return str;
1178 }
1179
1180 template <typename RegType, typename AddrType>
1181 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1182 const std::vector<RegType*> registers,
1183 const std::vector<AddrType> addresses,
1184 std::string (AssemblerTest::*GetRName)(const RegType&),
1185 std::string (AssemblerTest::*GetAName)(const AddrType&),
1186 const std::string& fmt) {
1187 WarnOnCombinations(addresses.size() * registers.size());
1188 std::string str;
1189 for (auto reg : registers) {
1190 for (auto addr : addresses) {
1191 if (f != nullptr) {
1192 (assembler_.get()->*f)(*reg, addr);
1193 }
1194 std::string base = fmt;
1195
1196 std::string reg_string = (this->*GetRName)(*reg);
1197 size_t reg_index;
1198 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1199 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1200 }
1201
1202 std::string addr_string = (this->*GetAName)(addr);
1203 size_t addr_index;
1204 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1205 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1206 }
1207
1208 if (str.size() > 0) {
1209 str += "\n";
1210 }
1211 str += base;
1212 }
1213 }
1214 // Add a newline at the end.
1215 str += "\n";
1216 return str;
1217 }
1218
1219 template <typename AddrType, typename RegType>
1220 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1221 const std::vector<AddrType> addresses,
1222 const std::vector<RegType*> registers,
1223 std::string (AssemblerTest::*GetAName)(const AddrType&),
1224 std::string (AssemblerTest::*GetRName)(const RegType&),
1225 const std::string& fmt) {
1226 WarnOnCombinations(addresses.size() * registers.size());
1227 std::string str;
1228 for (auto addr : addresses) {
1229 for (auto reg : registers) {
1230 if (f != nullptr) {
1231 (assembler_.get()->*f)(addr, *reg);
1232 }
1233 std::string base = fmt;
1234
1235 std::string addr_string = (this->*GetAName)(addr);
1236 size_t addr_index;
1237 if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1238 base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1239 }
1240
1241 std::string reg_string = (this->*GetRName)(*reg);
1242 size_t reg_index;
1243 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1244 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1245 }
1246
1247 if (str.size() > 0) {
1248 str += "\n";
1249 }
1250 str += base;
1251 }
1252 }
1253 // Add a newline at the end.
1254 str += "\n";
1255 return str;
1256 }
1257
1258 //
1259 // Register repeats.
1260 //
1261
Andreas Gampe851df202014-11-12 14:05:46 -08001262 template <typename RegType>
1263 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1264 const std::vector<RegType*> registers,
1265 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001266 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001267 std::string str;
1268 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001269 if (f != nullptr) {
1270 (assembler_.get()->*f)(*reg);
1271 }
Andreas Gampe851df202014-11-12 14:05:46 -08001272 std::string base = fmt;
1273
1274 std::string reg_string = (this->*GetName)(*reg);
1275 size_t reg_index;
1276 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1277 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1278 }
1279
1280 if (str.size() > 0) {
1281 str += "\n";
1282 }
1283 str += base;
1284 }
1285 // Add a newline at the end.
1286 str += "\n";
1287 return str;
1288 }
1289
1290 template <typename Reg1, typename Reg2>
1291 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1292 const std::vector<Reg1*> reg1_registers,
1293 const std::vector<Reg2*> reg2_registers,
1294 std::string (AssemblerTest::*GetName1)(const Reg1&),
1295 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001296 const std::string& fmt) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001297 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1298
Andreas Gampe851df202014-11-12 14:05:46 -08001299 std::string str;
1300 for (auto reg1 : reg1_registers) {
1301 for (auto reg2 : reg2_registers) {
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 // If the assembly file needs a header, return it in a sub-class.
1514 virtual const char* GetAssemblyHeader() {
1515 return nullptr;
1516 }
1517
1518 void WarnOnCombinations(size_t count) {
1519 if (count > kWarnManyCombinationsThreshold) {
1520 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1521 }
1522 }
1523
Aart Bikcaa31e72017-09-14 17:08:50 -07001524 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001525 static constexpr const char* REG_TOKEN = "{reg}";
1526 static constexpr const char* REG1_TOKEN = "{reg1}";
1527 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001528 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001529 static constexpr const char* IMM_TOKEN = "{imm}";
1530
1531 private:
Andreas Gampe851df202014-11-12 14:05:46 -08001532 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001533 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1534 size_t imm_bytes,
1535 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001536 const std::vector<Reg*> registers = GetRegisters();
1537 std::string str;
1538 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001539
1540 WarnOnCombinations(registers.size() * imms.size());
1541
Andreas Gampe851df202014-11-12 14:05:46 -08001542 for (auto reg : registers) {
1543 for (int64_t imm : imms) {
1544 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001545 if (f != nullptr) {
1546 (assembler_.get()->*f)(*reg, new_imm);
1547 }
Andreas Gampe851df202014-11-12 14:05:46 -08001548 std::string base = fmt;
1549
1550 std::string reg_string = GetRegName<kRegView>(*reg);
1551 size_t reg_index;
1552 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1553 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1554 }
1555
1556 size_t imm_index = base.find(IMM_TOKEN);
1557 if (imm_index != std::string::npos) {
1558 std::ostringstream sreg;
1559 sreg << imm;
1560 std::string imm_string = sreg.str();
1561 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1562 }
1563
1564 if (str.size() > 0) {
1565 str += "\n";
1566 }
1567 str += base;
1568 }
1569 }
1570 // Add a newline at the end.
1571 str += "\n";
1572 return str;
1573 }
1574
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001575 // Override this to pad the code with NOPs to a certain size if needed.
1576 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1577 }
1578
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001579 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001580 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001581 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001582 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001583 MemoryRegion code(&(*data)[0], data->size());
1584 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001585 Pad(*data);
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001586 test_helper_->Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001587 }
1588
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001589 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001590
Vladimir Marko93205e32016-04-13 11:59:46 +01001591 ArenaPool pool_;
1592 std::unique_ptr<ArenaAllocator> arena_;
Ian Rogers700a4022014-05-19 16:49:03 -07001593 std::unique_ptr<Ass> assembler_;
Andreas Gampe03b9ee42015-04-24 21:41:45 -07001594 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001595
Andreas Gampe851df202014-11-12 14:05:46 -08001596 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001597};
1598
1599} // namespace art
1600
1601#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_