blob: c2e5064faf5aa9b97687095b01c64f9ca7eb74db [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
Vladimir Marko176362a2022-11-08 11:47:50 +000029#include "base/macros.h"
David Sehr3215fff2018-04-03 17:10:12 -070030#include "base/malloc_arena_pool.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070031#include "assembler_test_base.h"
32#include "common_runtime_test.h" // For ScratchFile
Andreas Gampe5a4fa822014-03-31 16:50:12 -070033
Vladimir Marko176362a2022-11-08 11:47:50 +000034namespace art HIDDEN {
Andreas Gampe5a4fa822014-03-31 16:50:12 -070035
Andreas Gampe851df202014-11-12 14:05:46 -080036// Helper for a constexpr string length.
37constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
38 return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
39}
40
Andreas Gampe849cc5e2014-11-18 13:46:46 -080041enum class RegisterView { // private
42 kUsePrimaryName,
Chao-ying Fud23840d2015-04-07 16:03:04 -070043 kUseSecondaryName,
44 kUseTertiaryName,
45 kUseQuaternaryName,
Andreas Gampe849cc5e2014-11-18 13:46:46 -080046};
47
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +000048// For use in the template as the default type to get a nonvector registers version.
49struct NoVectorRegs {};
50
Aart Bikcaa31e72017-09-14 17:08:50 -070051template<typename Ass,
52 typename Addr,
53 typename Reg,
54 typename FPReg,
55 typename Imm,
56 typename VecReg = NoVectorRegs>
David Srbeckyd6e14e02020-07-01 13:19:17 +010057class AssemblerTest : public AssemblerTestBase {
Andreas Gampe5a4fa822014-03-31 16:50:12 -070058 public:
59 Ass* GetAssembler() {
60 return assembler_.get();
61 }
62
Stefano Cianciulli86c4b392022-06-09 14:46:08 +000063 using TestFn = std::string (*)(AssemblerTest *, Ass *);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070064
Andreas Gampe2e965ac2016-11-03 17:24:15 -070065 void DriverFn(TestFn f, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070066 DriverWrapper(f(this, assembler_.get()), test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070067 }
68
69 // This driver assumes the assembler has already been called.
Andreas Gampe2e965ac2016-11-03 17:24:15 -070070 void DriverStr(const std::string& assembly_string, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070071 DriverWrapper(assembly_string, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070072 }
73
Aart Bikcaa31e72017-09-14 17:08:50 -070074 //
75 // Register repeats.
76 //
77
Andreas Gampe2e965ac2016-11-03 17:24:15 -070078 std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080079 return RepeatTemplatedRegister<Reg>(f,
80 GetRegisters(),
81 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
82 fmt);
83 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070084
Andreas Gampe2e965ac2016-11-03 17:24:15 -070085 std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080086 return RepeatTemplatedRegister<Reg>(f,
87 GetRegisters(),
88 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
89 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070090 }
91
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +010092 std::string RepeatRR(void (Ass::*f)(Reg, Reg),
93 const std::string& fmt,
94 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -080095 return RepeatTemplatedRegisters<Reg, Reg>(f,
96 GetRegisters(),
97 GetRegisters(),
98 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
99 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100100 fmt,
101 except);
Andreas Gampe851df202014-11-12 14:05:46 -0800102 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700103
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700104 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -0700105 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
106 GetRegisters(),
107 GetRegisters(),
108 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
109 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
110 fmt);
111 }
112
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100113 std::string Repeatrr(void (Ass::*f)(Reg, Reg),
114 const std::string& fmt,
115 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -0800116 return RepeatTemplatedRegisters<Reg, Reg>(f,
117 GetRegisters(),
118 GetRegisters(),
119 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
120 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100121 fmt,
122 except);
Andreas Gampe851df202014-11-12 14:05:46 -0800123 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700124
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100125 std::string Repeatww(void (Ass::*f)(Reg, Reg),
126 const std::string& fmt,
127 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Aart Bikf7754e82017-09-20 10:33:06 -0700128 return RepeatTemplatedRegisters<Reg, Reg>(f,
129 GetRegisters(),
130 GetRegisters(),
131 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
132 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100133 fmt,
134 except);
Aart Bikf7754e82017-09-20 10:33:06 -0700135 }
136
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100137 std::string Repeatbb(void (Ass::*f)(Reg, Reg),
138 const std::string& fmt,
139 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Aart Bikf7754e82017-09-20 10:33:06 -0700140 return RepeatTemplatedRegisters<Reg, Reg>(f,
141 GetRegisters(),
142 GetRegisters(),
143 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
144 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100145 fmt,
146 except);
Aart Bikf7754e82017-09-20 10:33:06 -0700147 }
148
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700149 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700150 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
151 GetRegisters(),
152 GetRegisters(),
153 GetRegisters(),
154 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
155 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
156 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
157 fmt);
158 }
159
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100160 std::string Repeatrb(void (Ass::*f)(Reg, Reg),
161 const std::string& fmt,
162 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700163 return RepeatTemplatedRegisters<Reg, Reg>(f,
164 GetRegisters(),
165 GetRegisters(),
166 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
167 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100168 fmt,
169 except);
Chao-ying Fud23840d2015-04-07 16:03:04 -0700170 }
171
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100172 std::string RepeatRr(void (Ass::*f)(Reg, Reg),
173 const std::string& fmt,
174 const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
Andreas Gampe851df202014-11-12 14:05:46 -0800175 return RepeatTemplatedRegisters<Reg, Reg>(f,
176 GetRegisters(),
177 GetRegisters(),
178 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
179 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +0100180 fmt,
181 except);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700182 }
183
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700184 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800185 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700186 }
187
Aart Bikf7754e82017-09-20 10:33:06 -0700188 std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800189 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
190 }
191
Aart Bikf7754e82017-09-20 10:33:06 -0700192 std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
193 return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
194 }
195
196 std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
197 return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
198 }
199
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200200 template <typename Reg1, typename Reg2, typename ImmType>
201 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
202 int imm_bits,
203 const std::vector<Reg1*> reg1_registers,
204 const std::vector<Reg2*> reg2_registers,
205 std::string (AssemblerTest::*GetName1)(const Reg1&),
206 std::string (AssemblerTest::*GetName2)(const Reg2&),
Chris Larsene3660592016-11-09 11:13:42 -0800207 const std::string& fmt,
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000208 int bias = 0,
209 int multiplier = 1) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700210 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800211 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Chris Larsendbce0d72015-09-17 13:34:00 -0700212
213 for (auto reg1 : reg1_registers) {
214 for (auto reg2 : reg2_registers) {
215 for (int64_t imm : imms) {
216 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700217 if (f != nullptr) {
218 (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
219 }
Chris Larsendbce0d72015-09-17 13:34:00 -0700220 std::string base = fmt;
221
Vladimir Marko20a23082023-05-11 13:57:43 +0000222 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
223 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
224 ReplaceImm(imm, bias, multiplier, &base);
Chris Larsendbce0d72015-09-17 13:34:00 -0700225
Chris Larsendbce0d72015-09-17 13:34:00 -0700226 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000227 str += "\n";
Chris Larsendbce0d72015-09-17 13:34:00 -0700228 }
229 }
230 }
Chris Larsendbce0d72015-09-17 13:34:00 -0700231 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&),
Stefano Cianciullib205efd2022-06-08 15:28:46 +0000243 const std::string& fmt,
Chris Larsene3660592016-11-09 11:13:42 -0800244 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
Vladimir Marko20a23082023-05-11 13:57:43 +0000258 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
259 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
260 ReplaceReg(REG3_TOKEN, (this->*GetName3)(*reg3), &base);
261 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
Chris Larsene3660592016-11-09 11:13:42 -0800262
Chris Larsene3660592016-11-09 11:13:42 -0800263 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000264 str += "\n";
Chris Larsene3660592016-11-09 11:13:42 -0800265 }
266 }
267 }
268 }
Chris Larsene3660592016-11-09 11:13:42 -0800269 return str;
270 }
271
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800272 template <typename ImmType, typename Reg1, typename Reg2>
273 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
274 const std::vector<Reg1*> reg1_registers,
275 const std::vector<Reg2*> reg2_registers,
276 std::string (AssemblerTest::*GetName1)(const Reg1&),
277 std::string (AssemblerTest::*GetName2)(const Reg2&),
278 int imm_bits,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700279 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800280 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
281
282 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
283
284 std::string str;
285 for (auto reg1 : reg1_registers) {
286 for (auto reg2 : reg2_registers) {
287 for (int64_t imm : imms) {
288 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700289 if (f != nullptr) {
290 (assembler_.get()->*f)(new_imm, *reg1, *reg2);
291 }
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800292 std::string base = fmt;
293
Vladimir Marko20a23082023-05-11 13:57:43 +0000294 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
295 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
296 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800297
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800298 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000299 str += "\n";
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800300 }
301 }
302 }
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800303 return str;
304 }
305
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200306 template <typename RegType, typename ImmType>
307 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800308 int imm_bits,
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200309 const std::vector<RegType*> registers,
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800310 std::string (AssemblerTest::*GetName)(const RegType&),
Chris Larsene3660592016-11-09 11:13:42 -0800311 const std::string& fmt,
312 int bias) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200313 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800314 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200315
316 for (auto reg : registers) {
317 for (int64_t imm : imms) {
318 ImmType new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700319 if (f != nullptr) {
320 (assembler_.get()->*f)(*reg, new_imm + bias);
321 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200322 std::string base = fmt;
323
Vladimir Marko20a23082023-05-11 13:57:43 +0000324 ReplaceReg(REG_TOKEN, (this->*GetName)(*reg), &base);
325 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200326
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200327 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000328 str += "\n";
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200329 }
330 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200331 return str;
332 }
333
Lifang Xia593fc2e2023-03-15 13:36:40 +0800334 template <typename RegType, typename ImmType>
335 std::string RepeatTemplatedRegisterImmBitsShift(
336 void (Ass::*f)(RegType, ImmType),
337 int imm_bits,
338 int shift,
339 const std::vector<RegType*> registers,
340 std::string (AssemblerTest::*GetName)(const RegType&),
341 const std::string& fmt,
342 int bias) {
343 std::string str;
344 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
345
346 for (auto reg : registers) {
347 for (int64_t imm : imms) {
348 ImmType new_imm = CreateImmediate(imm);
349 if (f != nullptr) {
350 (assembler_.get()->*f)(*reg, new_imm + bias);
351 }
352 std::string base = fmt;
353
Vladimir Marko20a23082023-05-11 13:57:43 +0000354 ReplaceReg(REG_TOKEN, (this->*GetName)(*reg), &base);
355 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800356
Lifang Xia593fc2e2023-03-15 13:36:40 +0800357 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000358 str += "\n";
Lifang Xia593fc2e2023-03-15 13:36:40 +0800359 }
360 }
Lifang Xia593fc2e2023-03-15 13:36:40 +0800361 return str;
362 }
363
364 template <typename ImmType>
365 std::string RepeatTemplatedImmBitsShift(
366 void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
367 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
368
369 WarnOnCombinations(imms.size());
370
371 std::string str;
372
373 for (int64_t imm : imms) {
374 ImmType new_imm = CreateImmediate(imm);
375 if (f != nullptr) {
376 (assembler_.get()->*f)(new_imm + bias);
377 }
378 std::string base = fmt;
379
Vladimir Marko20a23082023-05-11 13:57:43 +0000380 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800381
Lifang Xia593fc2e2023-03-15 13:36:40 +0800382 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000383 str += "\n";
Lifang Xia593fc2e2023-03-15 13:36:40 +0800384 }
Lifang Xia593fc2e2023-03-15 13:36:40 +0800385 return str;
386 }
387
388 template <typename Reg1, typename Reg2, typename ImmType>
389 std::string RepeatTemplatedRegistersImmBitsShift(
390 void (Ass::*f)(Reg1, Reg2, ImmType),
391 int imm_bits,
392 int shift,
393 const std::vector<Reg1*> reg1_registers,
394 const std::vector<Reg2*> reg2_registers,
395 std::string (AssemblerTest::*GetName1)(const Reg1&),
396 std::string (AssemblerTest::*GetName2)(const Reg2&),
397 const std::string& fmt,
398 int bias = 0,
399 int multiplier = 1) {
400 std::string str;
401 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift);
402
403 for (auto reg1 : reg1_registers) {
404 for (auto reg2 : reg2_registers) {
405 for (int64_t imm : imms) {
406 ImmType new_imm = CreateImmediate(imm);
407 if (f != nullptr) {
408 (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
409 }
410 std::string base = fmt;
411
Vladimir Marko20a23082023-05-11 13:57:43 +0000412 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
413 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
414 ReplaceImm(imm, bias, multiplier, &base);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800415
Lifang Xia593fc2e2023-03-15 13:36:40 +0800416 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000417 str += "\n";
Lifang Xia593fc2e2023-03-15 13:36:40 +0800418 }
419 }
420 }
Lifang Xia593fc2e2023-03-15 13:36:40 +0800421 return str;
422 }
423
424 template <typename ImmType>
425 std::string RepeatIbS(
426 void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
427 return RepeatTemplatedImmBitsShift<ImmType>(f, imm_bits, shift, fmt, bias);
428 }
429
430 template <typename ImmType>
431 std::string RepeatRIbS(
432 void (Ass::*f)(Reg, ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) {
433 return RepeatTemplatedRegisterImmBitsShift<Reg, ImmType>(
434 f,
435 imm_bits,
436 shift,
437 GetRegisters(),
438 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
439 fmt,
440 bias);
441 }
442
443 template <typename ImmType>
444 std::string RepeatRRIbS(void (Ass::*f)(Reg, Reg, ImmType),
445 int imm_bits,
446 int shift,
447 const std::string& fmt,
448 int bias = 0) {
449 return RepeatTemplatedRegistersImmBitsShift<Reg, Reg, ImmType>(
450 f,
451 imm_bits,
452 shift,
453 GetRegisters(),
454 GetRegisters(),
455 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
456 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
457 fmt,
458 bias);
459 }
460
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200461 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800462 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
463 int imm_bits,
464 const std::string& fmt,
465 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200466 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
467 imm_bits,
468 GetRegisters(),
469 GetRegisters(),
470 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
471 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800472 fmt,
473 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200474 }
475
476 template <typename ImmType>
Chris Larsene3660592016-11-09 11:13:42 -0800477 std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
478 int imm_bits,
479 const std::string& fmt,
480 int bias = 0) {
481 return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
482 imm_bits,
483 GetRegisters(),
484 GetRegisters(),
485 GetRegisters(),
486 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
487 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
488 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
489 fmt,
490 bias);
491 }
492
493 template <typename ImmType>
494 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200495 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
496 imm_bits,
497 GetRegisters(),
498 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800499 fmt,
500 bias);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200501 }
502
503 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700504 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
505 int imm_bits,
Chris Larsene3660592016-11-09 11:13:42 -0800506 const std::string& fmt,
507 int bias = 0) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200508 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
509 imm_bits,
510 GetFPRegisters(),
511 GetRegisters(),
512 &AssemblerTest::GetFPRegName,
513 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
Chris Larsene3660592016-11-09 11:13:42 -0800514 fmt,
515 bias);
Chris Larsendbce0d72015-09-17 13:34:00 -0700516 }
517
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700518 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800519 return RepeatTemplatedRegisters<FPReg, FPReg>(f,
520 GetFPRegisters(),
521 GetFPRegisters(),
522 &AssemblerTest::GetFPRegName,
523 &AssemblerTest::GetFPRegName,
524 fmt);
525 }
526
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700527 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700528 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
529 GetFPRegisters(),
530 GetFPRegisters(),
531 GetFPRegisters(),
532 &AssemblerTest::GetFPRegName,
533 &AssemblerTest::GetFPRegName,
534 &AssemblerTest::GetFPRegName,
535 fmt);
536 }
537
Lifang Xia60fdcb22023-03-15 13:36:40 +0800538 std::string RepeatFFFF(void (Ass::*f)(FPReg, FPReg, FPReg, FPReg), const std::string& fmt) {
539 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg, FPReg>(f,
540 GetFPRegisters(),
541 GetFPRegisters(),
542 GetFPRegisters(),
543 GetFPRegisters(),
544 &AssemblerTest::GetFPRegName,
545 &AssemblerTest::GetFPRegName,
546 &AssemblerTest::GetFPRegName,
547 &AssemblerTest::GetFPRegName,
548 fmt);
549 }
550
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700551 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
Alexey Frunze674b9ee2016-09-20 14:54:15 -0700552 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
553 f,
554 GetFPRegisters(),
555 GetFPRegisters(),
556 GetRegisters(),
557 &AssemblerTest::GetFPRegName,
558 &AssemblerTest::GetFPRegName,
559 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
560 fmt);
561 }
562
Chris Larsendbce0d72015-09-17 13:34:00 -0700563 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
564 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700565 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400566 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
Chris Larsendbce0d72015-09-17 13:34:00 -0700567 GetFPRegisters(),
568 GetFPRegisters(),
569 &AssemblerTest::GetFPRegName,
570 &AssemblerTest::GetFPRegName,
571 imm_bytes,
572 fmt);
Mark Mendellfb8d2792015-03-31 22:16:59 -0400573 }
574
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800575 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700576 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
577 int imm_bits,
578 const std::string& fmt) {
Alexey Frunzea8aaf5a2016-06-27 14:48:20 -0700579 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
580 imm_bits,
581 GetFPRegisters(),
582 GetFPRegisters(),
583 &AssemblerTest::GetFPRegName,
584 &AssemblerTest::GetFPRegName,
585 fmt);
586 }
587
588 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700589 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
590 int imm_bits,
591 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800592 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
593 GetFPRegisters(),
594 GetFPRegisters(),
595 &AssemblerTest::GetFPRegName,
596 &AssemblerTest::GetFPRegName,
597 imm_bits,
598 fmt);
599 }
600
Lifang Xia60fdcb22023-03-15 13:36:40 +0800601 std::string RepeatRFF(void (Ass::*f)(Reg, FPReg, FPReg), const std::string& fmt) {
602 return RepeatTemplatedRegisters<Reg, FPReg, FPReg>(
603 f,
604 GetRegisters(),
605 GetFPRegisters(),
606 GetFPRegisters(),
607 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
608 &AssemblerTest::GetFPRegName,
609 &AssemblerTest::GetFPRegName,
610 fmt);
611 }
612
613 template <typename ImmType>
614 std::string RepeatRFIb(void (Ass::*f)(Reg, FPReg, ImmType),
615 int imm_bits,
616 const std::string& fmt) {
617 return RepeatTemplatedRegistersImmBits<Reg, FPReg, ImmType>(
618 f,
619 imm_bits,
620 GetRegisters(),
621 GetFPRegisters(),
622 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
623 &AssemblerTest::GetFPRegName,
624 fmt);
625 }
626
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700627 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800628 return RepeatTemplatedRegisters<FPReg, Reg>(f,
629 GetFPRegisters(),
630 GetRegisters(),
631 &AssemblerTest::GetFPRegName,
632 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
633 fmt);
634 }
635
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700636 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800637 return RepeatTemplatedRegisters<FPReg, Reg>(f,
638 GetFPRegisters(),
639 GetRegisters(),
640 &AssemblerTest::GetFPRegName,
641 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
642 fmt);
643 }
644
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700645 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800646 return RepeatTemplatedRegisters<Reg, FPReg>(f,
647 GetRegisters(),
648 GetFPRegisters(),
649 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
650 &AssemblerTest::GetFPRegName,
651 fmt);
652 }
653
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700654 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800655 return RepeatTemplatedRegisters<Reg, FPReg>(f,
656 GetRegisters(),
657 GetFPRegisters(),
658 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
659 &AssemblerTest::GetFPRegName,
660 fmt);
661 }
662
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700663 std::string RepeatI(void (Ass::*f)(const Imm&),
664 size_t imm_bytes,
665 const std::string& fmt,
Andreas Gampe851df202014-11-12 14:05:46 -0800666 bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700667 std::string str;
Andreas Gampe851df202014-11-12 14:05:46 -0800668 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800669
670 WarnOnCombinations(imms.size());
671
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700672 for (int64_t imm : imms) {
Ian Rogerscf7f1912014-10-22 22:06:39 -0700673 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -0700674 if (f != nullptr) {
675 (assembler_.get()->*f)(new_imm);
676 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700677 std::string base = fmt;
678
Vladimir Marko20a23082023-05-11 13:57:43 +0000679 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700680
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700681 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +0000682 str += "\n";
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700683 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700684 return str;
685 }
686
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000687 std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
688 return RepeatTemplatedRegisters<VecReg, VecReg>(f,
689 GetVectorRegisters(),
690 GetVectorRegisters(),
691 &AssemblerTest::GetVecRegName,
692 &AssemblerTest::GetVecRegName,
693 fmt);
694 }
695
696 std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
697 return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
698 GetVectorRegisters(),
699 GetVectorRegisters(),
700 GetVectorRegisters(),
701 &AssemblerTest::GetVecRegName,
702 &AssemblerTest::GetVecRegName,
703 &AssemblerTest::GetVecRegName,
704 fmt);
705 }
706
707 std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
708 return RepeatTemplatedRegisters<VecReg, Reg>(
709 f,
710 GetVectorRegisters(),
711 GetRegisters(),
712 &AssemblerTest::GetVecRegName,
713 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
714 fmt);
715 }
716
717 template <typename ImmType>
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200718 std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
719 int imm_bits,
720 std::string fmt,
721 int bias = 0) {
722 return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
723 imm_bits,
724 GetVectorRegisters(),
725 &AssemblerTest::GetVecRegName,
726 fmt,
727 bias);
728 }
729
730 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000731 std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
732 int imm_bits,
733 const std::string& fmt,
734 int bias = 0,
735 int multiplier = 1) {
736 return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
737 f,
738 imm_bits,
739 GetVectorRegisters(),
740 GetRegisters(),
741 &AssemblerTest::GetVecRegName,
742 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
743 fmt,
744 bias,
745 multiplier);
746 }
747
748 template <typename ImmType>
Lena Djokic3309c012017-10-13 14:34:32 +0200749 std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
750 int imm_bits,
751 const std::string& fmt,
752 int bias = 0,
753 int multiplier = 1) {
754 return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
755 f,
756 imm_bits,
757 GetRegisters(),
758 GetVectorRegisters(),
759 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
760 &AssemblerTest::GetVecRegName,
761 fmt,
762 bias,
763 multiplier);
764 }
765
766 template <typename ImmType>
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000767 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
768 int imm_bits,
769 const std::string& fmt,
770 int bias = 0) {
771 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
772 imm_bits,
773 GetVectorRegisters(),
774 GetVectorRegisters(),
775 &AssemblerTest::GetVecRegName,
776 &AssemblerTest::GetVecRegName,
777 fmt,
778 bias);
779 }
780
Andreas Gampe851df202014-11-12 14:05:46 -0800781 // The following functions are public so that TestFn can use them...
782
Aart Bikcaa31e72017-09-14 17:08:50 -0700783 // Returns a vector of address used by any of the repeat methods
784 // involving an "A" (e.g. RepeatA).
785 virtual std::vector<Addr> GetAddresses() = 0;
786
787 // Returns a vector of registers used by any of the repeat methods
788 // involving an "R" (e.g. RepeatR).
Andreas Gampe851df202014-11-12 14:05:46 -0800789 virtual std::vector<Reg*> GetRegisters() = 0;
790
Aart Bikcaa31e72017-09-14 17:08:50 -0700791 // Returns a vector of fp-registers used by any of the repeat methods
792 // involving an "F" (e.g. RepeatFF).
Andreas Gampe851df202014-11-12 14:05:46 -0800793 virtual std::vector<FPReg*> GetFPRegisters() {
794 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
795 UNREACHABLE();
796 }
797
Aart Bikcaa31e72017-09-14 17:08:50 -0700798 // Returns a vector of dedicated simd-registers used by any of the repeat
799 // methods involving an "V" (e.g. RepeatVV).
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000800 virtual std::vector<VecReg*> GetVectorRegisters() {
801 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
802 UNREACHABLE();
803 }
804
Andreas Gampe851df202014-11-12 14:05:46 -0800805 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
Stefano Cianciulli78f3c722023-05-16 10:32:54 +0000806 virtual std::string GetSecondaryRegisterName([[maybe_unused]] const Reg& reg) {
Andreas Gampe851df202014-11-12 14:05:46 -0800807 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
808 UNREACHABLE();
809 }
810
Chao-ying Fud23840d2015-04-07 16:03:04 -0700811 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
Stefano Cianciulli78f3c722023-05-16 10:32:54 +0000812 virtual std::string GetTertiaryRegisterName([[maybe_unused]] const Reg& reg) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700813 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
814 UNREACHABLE();
815 }
816
817 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
Stefano Cianciulli78f3c722023-05-16 10:32:54 +0000818 virtual std::string GetQuaternaryRegisterName([[maybe_unused]] const Reg& reg) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700819 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
820 UNREACHABLE();
821 }
822
Calin Juravle9aec02f2014-11-18 23:06:35 +0000823 std::string GetRegisterName(const Reg& reg) {
824 return GetRegName<RegisterView::kUsePrimaryName>(reg);
825 }
826
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700827 protected:
Igor Murashkin2ffb7032017-11-08 13:35:21 -0800828 AssemblerTest() {}
Andreas Gampe851df202014-11-12 14:05:46 -0800829
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100830 void SetUp() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100831 AssemblerTestBase::SetUp();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100832 allocator_.reset(new ArenaAllocator(&pool_));
833 assembler_.reset(CreateAssembler(allocator_.get()));
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700834 SetUpHelpers();
835 }
836
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100837 void TearDown() override {
David Srbeckyd6e14e02020-07-01 13:19:17 +0100838 AssemblerTestBase::TearDown();
Vladimir Marko93205e32016-04-13 11:59:46 +0100839 assembler_.reset();
Vladimir Marko69d310e2017-10-09 14:12:23 +0100840 allocator_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700841 }
842
Chris Larsen3add9cb2016-04-14 14:01:33 -0700843 // Override this to set up any architecture-specific things, e.g., CPU revision.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100844 virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
845 return new (allocator) Ass(allocator);
Chris Larsen3add9cb2016-04-14 14:01:33 -0700846 }
847
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700848 // Override this to set up any architecture-specific things, e.g., register vectors.
849 virtual void SetUpHelpers() {}
850
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700851 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800852 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700853 std::vector<int64_t> res;
854 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800855 if (!as_uint) {
856 res.push_back(-1);
857 } else {
858 res.push_back(0xFF);
859 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700860 res.push_back(0x12);
861 if (imm_bytes >= 2) {
862 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800863 if (!as_uint) {
864 res.push_back(-0x1234);
865 } else {
866 res.push_back(0xFFFF);
867 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700868 if (imm_bytes >= 4) {
869 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800870 if (!as_uint) {
871 res.push_back(-0x12345678);
872 } else {
873 res.push_back(0xFFFFFFFF);
874 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700875 if (imm_bytes >= 6) {
876 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800877 if (!as_uint) {
878 res.push_back(-0x123456789ABC);
879 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700880 if (imm_bytes >= 8) {
881 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800882 if (!as_uint) {
883 res.push_back(-0x123456789ABCDEF0);
884 } else {
885 res.push_back(0xFFFFFFFFFFFFFFFF);
886 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700887 }
888 }
889 }
890 }
891 return res;
892 }
893
Chris Larsendbce0d72015-09-17 13:34:00 -0700894 const int kMaxBitsExhaustiveTest = 8;
895
896 // Create a couple of immediate values up to the number of bits given.
Lifang Xia593fc2e2023-03-15 13:36:40 +0800897 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits,
898 bool as_uint = false,
899 int shift = 0) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700900 CHECK_GT(imm_bits, 0);
901 CHECK_LE(imm_bits, 64);
902 std::vector<int64_t> res;
903
904 if (imm_bits <= kMaxBitsExhaustiveTest) {
905 if (as_uint) {
906 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
Lifang Xia593fc2e2023-03-15 13:36:40 +0800907 res.push_back(static_cast<int64_t>(i << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700908 }
909 } else {
910 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
Lifang Xia593fc2e2023-03-15 13:36:40 +0800911 res.push_back(i << shift);
Chris Larsendbce0d72015-09-17 13:34:00 -0700912 }
913 }
914 } else {
915 if (as_uint) {
916 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
917 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
918 i++) {
Lifang Xia593fc2e2023-03-15 13:36:40 +0800919 res.push_back(static_cast<int64_t>(i << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700920 }
921 for (int i = 0; i <= imm_bits; i++) {
922 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
923 ((MaxInt<uint64_t>(imm_bits) -
924 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
925 * i / imm_bits);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800926 res.push_back(static_cast<int64_t>(j << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700927 }
928 } else {
929 for (int i = 0; i <= imm_bits; i++) {
930 int64_t j = MinInt<int64_t>(imm_bits) +
931 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
932 MinInt<int64_t>(imm_bits))
933 * i) / imm_bits);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800934 res.push_back(static_cast<int64_t>(j << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700935 }
936 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
937 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
938 i++) {
Lifang Xia593fc2e2023-03-15 13:36:40 +0800939 res.push_back(static_cast<int64_t>(i << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700940 }
941 for (int i = 0; i <= imm_bits; i++) {
942 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
943 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
944 * i / imm_bits);
Lifang Xia593fc2e2023-03-15 13:36:40 +0800945 res.push_back(static_cast<int64_t>(j << shift));
Chris Larsendbce0d72015-09-17 13:34:00 -0700946 }
947 }
948 }
949
950 return res;
951 }
952
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700953 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700954 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700955
Aart Bikcaa31e72017-09-14 17:08:50 -0700956 //
957 // Addresses repeats.
958 //
959
960 // Repeats over addresses provided by fixture.
961 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
962 return RepeatA(f, GetAddresses(), fmt);
963 }
964
965 // Variant that takes explicit vector of addresss
966 // (to test restricted addressing modes set).
967 std::string RepeatA(void (Ass::*f)(const Addr&),
968 const std::vector<Addr>& a,
969 const std::string& fmt) {
970 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
971 }
972
973 // Repeats over addresses and immediates provided by fixture.
974 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
975 size_t imm_bytes,
976 const std::string& fmt) {
977 return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
978 }
979
980 // Variant that takes explicit vector of addresss
981 // (to test restricted addressing modes set).
982 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
983 size_t imm_bytes,
984 const std::vector<Addr>& a,
985 const std::string& fmt) {
986 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
987 }
988
989 // Repeats over registers and addresses provided by fixture.
990 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
991 return RepeatRA(f, GetAddresses(), fmt);
992 }
993
994 // Variant that takes explicit vector of addresss
995 // (to test restricted addressing modes set).
996 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
997 const std::vector<Addr>& a,
998 const std::string& fmt) {
999 return RepeatTemplatedRegMem<Reg, Addr>(
1000 f,
1001 GetRegisters(),
1002 a,
1003 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1004 &AssemblerTest::GetAddrName,
1005 fmt);
1006 }
1007
Aart Bikf7754e82017-09-20 10:33:06 -07001008 // Repeats over secondary registers and addresses provided by fixture.
1009 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1010 return RepeatrA(f, GetAddresses(), fmt);
1011 }
1012
1013 // Variant that takes explicit vector of addresss
1014 // (to test restricted addressing modes set).
1015 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
1016 const std::vector<Addr>& a,
1017 const std::string& fmt) {
1018 return RepeatTemplatedRegMem<Reg, Addr>(
1019 f,
1020 GetRegisters(),
1021 a,
1022 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1023 &AssemblerTest::GetAddrName,
1024 fmt);
1025 }
1026
1027 // Repeats over tertiary registers and addresses provided by fixture.
1028 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1029 return RepeatwA(f, GetAddresses(), fmt);
1030 }
1031
1032 // Variant that takes explicit vector of addresss
1033 // (to test restricted addressing modes set).
1034 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
1035 const std::vector<Addr>& a,
1036 const std::string& fmt) {
1037 return RepeatTemplatedRegMem<Reg, Addr>(
1038 f,
1039 GetRegisters(),
1040 a,
1041 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1042 &AssemblerTest::GetAddrName,
1043 fmt);
1044 }
1045
1046 // Repeats over quaternary registers and addresses provided by fixture.
1047 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
1048 return RepeatbA(f, GetAddresses(), fmt);
1049 }
1050
1051 // Variant that takes explicit vector of addresss
1052 // (to test restricted addressing modes set).
1053 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
1054 const std::vector<Addr>& a,
1055 const std::string& fmt) {
1056 return RepeatTemplatedRegMem<Reg, Addr>(
1057 f,
1058 GetRegisters(),
1059 a,
1060 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1061 &AssemblerTest::GetAddrName,
1062 fmt);
1063 }
1064
Aart Bikcaa31e72017-09-14 17:08:50 -07001065 // Repeats over fp-registers and addresses provided by fixture.
1066 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
1067 return RepeatFA(f, GetAddresses(), fmt);
1068 }
1069
1070 // Variant that takes explicit vector of addresss
1071 // (to test restricted addressing modes set).
1072 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1073 const std::vector<Addr>& a,
1074 const std::string& fmt) {
1075 return RepeatTemplatedRegMem<FPReg, Addr>(
1076 f,
1077 GetFPRegisters(),
1078 a,
1079 &AssemblerTest::GetFPRegName,
1080 &AssemblerTest::GetAddrName,
1081 fmt);
1082 }
1083
1084 // Repeats over addresses and registers provided by fixture.
1085 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1086 return RepeatAR(f, GetAddresses(), fmt);
1087 }
1088
1089 // Variant that takes explicit vector of addresss
1090 // (to test restricted addressing modes set).
1091 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1092 const std::vector<Addr>& a,
1093 const std::string& fmt) {
1094 return RepeatTemplatedMemReg<Addr, Reg>(
1095 f,
1096 a,
1097 GetRegisters(),
1098 &AssemblerTest::GetAddrName,
1099 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1100 fmt);
1101 }
1102
Aart Bikf7754e82017-09-20 10:33:06 -07001103 // Repeats over addresses and secondary registers provided by fixture.
1104 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1105 return RepeatAr(f, GetAddresses(), fmt);
1106 }
1107
1108 // Variant that takes explicit vector of addresss
1109 // (to test restricted addressing modes set).
1110 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1111 const std::vector<Addr>& a,
1112 const std::string& fmt) {
1113 return RepeatTemplatedMemReg<Addr, Reg>(
1114 f,
1115 a,
1116 GetRegisters(),
1117 &AssemblerTest::GetAddrName,
1118 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1119 fmt);
1120 }
1121
1122 // Repeats over addresses and tertiary registers provided by fixture.
1123 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1124 return RepeatAw(f, GetAddresses(), fmt);
1125 }
1126
1127 // Variant that takes explicit vector of addresss
1128 // (to test restricted addressing modes set).
1129 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1130 const std::vector<Addr>& a,
1131 const std::string& fmt) {
1132 return RepeatTemplatedMemReg<Addr, Reg>(
1133 f,
1134 a,
1135 GetRegisters(),
1136 &AssemblerTest::GetAddrName,
1137 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1138 fmt);
1139 }
1140
1141 // Repeats over addresses and quaternary registers provided by fixture.
1142 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1143 return RepeatAb(f, GetAddresses(), fmt);
1144 }
1145
1146 // Variant that takes explicit vector of addresss
1147 // (to test restricted addressing modes set).
1148 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1149 const std::vector<Addr>& a,
1150 const std::string& fmt) {
1151 return RepeatTemplatedMemReg<Addr, Reg>(
1152 f,
1153 a,
1154 GetRegisters(),
1155 &AssemblerTest::GetAddrName,
1156 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1157 fmt);
1158 }
1159
Aart Bikcaa31e72017-09-14 17:08:50 -07001160 // Repeats over addresses and fp-registers provided by fixture.
1161 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1162 return RepeatAF(f, GetAddresses(), fmt);
1163 }
1164
1165 // Variant that takes explicit vector of addresss
1166 // (to test restricted addressing modes set).
1167 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1168 const std::vector<Addr>& a,
1169 const std::string& fmt) {
1170 return RepeatTemplatedMemReg<Addr, FPReg>(
1171 f,
1172 a,
1173 GetFPRegisters(),
1174 &AssemblerTest::GetAddrName,
1175 &AssemblerTest::GetFPRegName,
1176 fmt);
1177 }
1178
1179 template <typename AddrType>
1180 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1181 const std::vector<AddrType> addresses,
1182 std::string (AssemblerTest::*GetAName)(const AddrType&),
1183 const std::string& fmt) {
1184 WarnOnCombinations(addresses.size());
1185 std::string str;
1186 for (auto addr : addresses) {
1187 if (f != nullptr) {
1188 (assembler_.get()->*f)(addr);
1189 }
1190 std::string base = fmt;
1191
Vladimir Marko20a23082023-05-11 13:57:43 +00001192 ReplaceAddr((this->*GetAName)(addr), &base);
Aart Bikcaa31e72017-09-14 17:08:50 -07001193
Aart Bikcaa31e72017-09-14 17:08:50 -07001194 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001195 str += "\n";
Aart Bikcaa31e72017-09-14 17:08:50 -07001196 }
Aart Bikcaa31e72017-09-14 17:08:50 -07001197 return str;
1198 }
1199
1200 template <typename AddrType>
1201 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1202 size_t imm_bytes,
1203 const std::vector<AddrType> addresses,
1204 std::string (AssemblerTest::*GetAName)(const AddrType&),
1205 const std::string& fmt) {
1206 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1207 WarnOnCombinations(addresses.size() * imms.size());
1208 std::string str;
1209 for (auto addr : addresses) {
1210 for (int64_t imm : imms) {
1211 Imm new_imm = CreateImmediate(imm);
1212 if (f != nullptr) {
1213 (assembler_.get()->*f)(addr, new_imm);
1214 }
1215 std::string base = fmt;
1216
Vladimir Marko20a23082023-05-11 13:57:43 +00001217 ReplaceAddr((this->*GetAName)(addr), &base);
1218 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
Aart Bikcaa31e72017-09-14 17:08:50 -07001219
Aart Bikcaa31e72017-09-14 17:08:50 -07001220 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001221 str += "\n";
Aart Bikcaa31e72017-09-14 17:08:50 -07001222 }
1223 }
Aart Bikcaa31e72017-09-14 17:08:50 -07001224 return str;
1225 }
1226
1227 template <typename RegType, typename AddrType>
1228 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1229 const std::vector<RegType*> registers,
1230 const std::vector<AddrType> addresses,
1231 std::string (AssemblerTest::*GetRName)(const RegType&),
1232 std::string (AssemblerTest::*GetAName)(const AddrType&),
1233 const std::string& fmt) {
1234 WarnOnCombinations(addresses.size() * registers.size());
1235 std::string str;
1236 for (auto reg : registers) {
1237 for (auto addr : addresses) {
1238 if (f != nullptr) {
1239 (assembler_.get()->*f)(*reg, addr);
1240 }
1241 std::string base = fmt;
1242
Vladimir Marko20a23082023-05-11 13:57:43 +00001243 ReplaceReg(REG_TOKEN, (this->*GetRName)(*reg), &base);
1244 ReplaceAddr((this->*GetAName)(addr), &base);
Aart Bikcaa31e72017-09-14 17:08:50 -07001245
Aart Bikcaa31e72017-09-14 17:08:50 -07001246 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001247 str += "\n";
Aart Bikcaa31e72017-09-14 17:08:50 -07001248 }
1249 }
Aart Bikcaa31e72017-09-14 17:08:50 -07001250 return str;
1251 }
1252
1253 template <typename AddrType, typename RegType>
1254 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1255 const std::vector<AddrType> addresses,
1256 const std::vector<RegType*> registers,
1257 std::string (AssemblerTest::*GetAName)(const AddrType&),
1258 std::string (AssemblerTest::*GetRName)(const RegType&),
1259 const std::string& fmt) {
1260 WarnOnCombinations(addresses.size() * registers.size());
1261 std::string str;
1262 for (auto addr : addresses) {
1263 for (auto reg : registers) {
1264 if (f != nullptr) {
1265 (assembler_.get()->*f)(addr, *reg);
1266 }
1267 std::string base = fmt;
1268
Vladimir Marko20a23082023-05-11 13:57:43 +00001269 ReplaceAddr((this->*GetAName)(addr), &base);
1270 ReplaceReg(REG_TOKEN, (this->*GetRName)(*reg), &base);
Aart Bikcaa31e72017-09-14 17:08:50 -07001271
Aart Bikcaa31e72017-09-14 17:08:50 -07001272 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001273 str += "\n";
Aart Bikcaa31e72017-09-14 17:08:50 -07001274 }
1275 }
Aart Bikcaa31e72017-09-14 17:08:50 -07001276 return str;
1277 }
1278
1279 //
1280 // Register repeats.
1281 //
1282
Andreas Gampe851df202014-11-12 14:05:46 -08001283 template <typename RegType>
1284 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1285 const std::vector<RegType*> registers,
1286 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001287 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -08001288 std::string str;
1289 for (auto reg : registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001290 if (f != nullptr) {
1291 (assembler_.get()->*f)(*reg);
1292 }
Andreas Gampe851df202014-11-12 14:05:46 -08001293 std::string base = fmt;
1294
Vladimir Marko20a23082023-05-11 13:57:43 +00001295 ReplaceReg(REG_TOKEN, (this->*GetName)(*reg), &base);
Andreas Gampe851df202014-11-12 14:05:46 -08001296
Andreas Gampe851df202014-11-12 14:05:46 -08001297 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001298 str += "\n";
Andreas Gampe851df202014-11-12 14:05:46 -08001299 }
Andreas Gampe851df202014-11-12 14:05:46 -08001300 return str;
1301 }
1302
1303 template <typename Reg1, typename Reg2>
1304 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1305 const std::vector<Reg1*> reg1_registers,
1306 const std::vector<Reg2*> reg2_registers,
1307 std::string (AssemblerTest::*GetName1)(const Reg1&),
1308 std::string (AssemblerTest::*GetName2)(const Reg2&),
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +01001309 const std::string& fmt,
1310 const std::vector<std::pair<Reg1, Reg2>>* except = nullptr) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001311 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1312
Andreas Gampe851df202014-11-12 14:05:46 -08001313 std::string str;
1314 for (auto reg1 : reg1_registers) {
1315 for (auto reg2 : reg2_registers) {
Ulya Trafimovicha5c529f2021-07-12 15:34:43 +01001316 // Check if this register pair is on the exception list. If so, skip it.
1317 if (except != nullptr) {
1318 const auto& pair = std::make_pair(*reg1, *reg2);
1319 if (std::find(except->begin(), except->end(), pair) != except->end()) {
1320 continue;
1321 }
1322 }
1323
Aart Bik5dafb3c2017-09-13 13:10:12 -07001324 if (f != nullptr) {
1325 (assembler_.get()->*f)(*reg1, *reg2);
1326 }
Andreas Gampe851df202014-11-12 14:05:46 -08001327 std::string base = fmt;
1328
Vladimir Marko20a23082023-05-11 13:57:43 +00001329 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
1330 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
Andreas Gampe851df202014-11-12 14:05:46 -08001331
Andreas Gampe851df202014-11-12 14:05:46 -08001332 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001333 str += "\n";
Andreas Gampe851df202014-11-12 14:05:46 -08001334 }
1335 }
Andreas Gampe851df202014-11-12 14:05:46 -08001336 return str;
1337 }
1338
Chris Larsen51417632015-10-02 13:24:25 -07001339 template <typename Reg1, typename Reg2>
1340 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1341 const std::vector<Reg1*> reg1_registers,
1342 const std::vector<Reg2*> reg2_registers,
1343 std::string (AssemblerTest::*GetName1)(const Reg1&),
1344 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001345 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -07001346 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1347
1348 std::string str;
1349 for (auto reg1 : reg1_registers) {
1350 for (auto reg2 : reg2_registers) {
1351 if (reg1 == reg2) continue;
Aart Bik5dafb3c2017-09-13 13:10:12 -07001352 if (f != nullptr) {
1353 (assembler_.get()->*f)(*reg1, *reg2);
1354 }
Chris Larsen51417632015-10-02 13:24:25 -07001355 std::string base = fmt;
1356
Vladimir Marko20a23082023-05-11 13:57:43 +00001357 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
1358 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
Chris Larsen51417632015-10-02 13:24:25 -07001359
Chris Larsen51417632015-10-02 13:24:25 -07001360 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001361 str += "\n";
Chris Larsen51417632015-10-02 13:24:25 -07001362 }
1363 }
Chris Larsen51417632015-10-02 13:24:25 -07001364 return str;
1365 }
1366
Chris Larsendbce0d72015-09-17 13:34:00 -07001367 template <typename Reg1, typename Reg2, typename Reg3>
1368 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1369 const std::vector<Reg1*> reg1_registers,
1370 const std::vector<Reg2*> reg2_registers,
1371 const std::vector<Reg3*> reg3_registers,
1372 std::string (AssemblerTest::*GetName1)(const Reg1&),
1373 std::string (AssemblerTest::*GetName2)(const Reg2&),
1374 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001375 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -07001376 std::string str;
1377 for (auto reg1 : reg1_registers) {
1378 for (auto reg2 : reg2_registers) {
1379 for (auto reg3 : reg3_registers) {
Aart Bik5dafb3c2017-09-13 13:10:12 -07001380 if (f != nullptr) {
1381 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1382 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001383 std::string base = fmt;
1384
Vladimir Marko20a23082023-05-11 13:57:43 +00001385 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
1386 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
1387 ReplaceReg(REG3_TOKEN, (this->*GetName3)(*reg3), &base);
Chris Larsendbce0d72015-09-17 13:34:00 -07001388
Chris Larsendbce0d72015-09-17 13:34:00 -07001389 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001390 str += "\n";
Chris Larsendbce0d72015-09-17 13:34:00 -07001391 }
1392 }
1393 }
Chris Larsendbce0d72015-09-17 13:34:00 -07001394 return str;
1395 }
1396
Lifang Xia60fdcb22023-03-15 13:36:40 +08001397 template <typename Reg1, typename Reg2, typename Reg3, typename Reg4>
1398 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3, Reg4),
1399 const std::vector<Reg1*>& reg1_registers,
1400 const std::vector<Reg2*>& reg2_registers,
1401 const std::vector<Reg3*>& reg3_registers,
1402 const std::vector<Reg4*>& reg4_registers,
1403 std::string (AssemblerTest::*GetName1)(const Reg1&),
1404 std::string (AssemblerTest::*GetName2)(const Reg2&),
1405 std::string (AssemblerTest::*GetName3)(const Reg3&),
1406 std::string (AssemblerTest::*GetName4)(const Reg4&),
1407 const std::string& fmt) {
1408 std::string str;
1409 for (auto reg1 : reg1_registers) {
1410 for (auto reg2 : reg2_registers) {
1411 for (auto reg3 : reg3_registers) {
1412 for (auto reg4 : reg4_registers) {
1413 if (f != nullptr) {
1414 (assembler_.get()->*f)(*reg1, *reg2, *reg3, *reg4);
1415 }
1416 std::string base = fmt;
1417
Vladimir Marko20a23082023-05-11 13:57:43 +00001418 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
1419 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
1420 ReplaceReg(REG3_TOKEN, (this->*GetName3)(*reg3), &base);
1421 ReplaceReg(REG4_TOKEN, (this->*GetName4)(*reg4), &base);
Lifang Xia60fdcb22023-03-15 13:36:40 +08001422
Lifang Xia60fdcb22023-03-15 13:36:40 +08001423 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001424 str += "\n";
Lifang Xia60fdcb22023-03-15 13:36:40 +08001425 }
1426 }
1427 }
1428 }
Lifang Xia60fdcb22023-03-15 13:36:40 +08001429 return str;
1430 }
1431
Mark Mendellfb8d2792015-03-31 22:16:59 -04001432 template <typename Reg1, typename Reg2>
1433 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1434 const std::vector<Reg1*> reg1_registers,
1435 const std::vector<Reg2*> reg2_registers,
1436 std::string (AssemblerTest::*GetName1)(const Reg1&),
1437 std::string (AssemblerTest::*GetName2)(const Reg2&),
1438 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001439 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -04001440 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1441 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1442
1443 std::string str;
1444 for (auto reg1 : reg1_registers) {
1445 for (auto reg2 : reg2_registers) {
1446 for (int64_t imm : imms) {
1447 Imm new_imm = CreateImmediate(imm);
Aart Bik5dafb3c2017-09-13 13:10:12 -07001448 if (f != nullptr) {
1449 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1450 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001451 std::string base = fmt;
1452
Vladimir Marko20a23082023-05-11 13:57:43 +00001453 ReplaceReg(REG1_TOKEN, (this->*GetName1)(*reg1), &base);
1454 ReplaceReg(REG2_TOKEN, (this->*GetName2)(*reg2), &base);
1455 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
Mark Mendellfb8d2792015-03-31 22:16:59 -04001456
Mark Mendellfb8d2792015-03-31 22:16:59 -04001457 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001458 str += "\n";
Mark Mendellfb8d2792015-03-31 22:16:59 -04001459 }
1460 }
1461 }
Mark Mendellfb8d2792015-03-31 22:16:59 -04001462 return str;
1463 }
1464
Aart Bikcaa31e72017-09-14 17:08:50 -07001465 std::string GetAddrName(const Addr& addr) {
1466 std::ostringstream saddr;
1467 saddr << addr;
1468 return saddr.str();
1469 }
1470
Andreas Gampe851df202014-11-12 14:05:46 -08001471 template <RegisterView kRegView>
1472 std::string GetRegName(const Reg& reg) {
1473 std::ostringstream sreg;
1474 switch (kRegView) {
1475 case RegisterView::kUsePrimaryName:
1476 sreg << reg;
1477 break;
1478
1479 case RegisterView::kUseSecondaryName:
1480 sreg << GetSecondaryRegisterName(reg);
1481 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -07001482
1483 case RegisterView::kUseTertiaryName:
1484 sreg << GetTertiaryRegisterName(reg);
1485 break;
1486
1487 case RegisterView::kUseQuaternaryName:
1488 sreg << GetQuaternaryRegisterName(reg);
1489 break;
Andreas Gampe851df202014-11-12 14:05:46 -08001490 }
1491 return sreg.str();
1492 }
1493
1494 std::string GetFPRegName(const FPReg& reg) {
1495 std::ostringstream sreg;
1496 sreg << reg;
1497 return sreg.str();
1498 }
1499
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001500 std::string GetVecRegName(const VecReg& reg) {
1501 std::ostringstream sreg;
1502 sreg << reg;
1503 return sreg.str();
1504 }
1505
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001506 void WarnOnCombinations(size_t count) {
1507 if (count > kWarnManyCombinationsThreshold) {
1508 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1509 }
1510 }
1511
Vladimir Marko20a23082023-05-11 13:57:43 +00001512 static void ReplaceReg(const std::string& reg_token,
1513 const std::string& replacement,
1514 /*inout*/ std::string* str) {
1515 size_t reg_index;
1516 while ((reg_index = str->find(reg_token)) != std::string::npos) {
1517 str->replace(reg_index, reg_token.length(), replacement);
1518 }
1519 }
1520
1521 static void ReplaceImm(int64_t imm,
1522 int64_t bias,
1523 int64_t multiplier,
1524 /*inout*/ std::string* str) {
1525 size_t imm_index = str->find(IMM_TOKEN);
1526 if (imm_index != std::string::npos) {
1527 std::ostringstream sreg;
1528 sreg << imm * multiplier + bias;
1529 std::string imm_string = sreg.str();
1530 str->replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1531 }
1532 }
1533
1534 static void ReplaceAddr(const std::string& replacement, /*inout*/ std::string* str) {
1535 size_t addr_index;
1536 if ((addr_index = str->find(ADDRESS_TOKEN)) != std::string::npos) {
1537 str->replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), replacement);
1538 }
1539 }
1540
Aart Bikcaa31e72017-09-14 17:08:50 -07001541 static constexpr const char* ADDRESS_TOKEN = "{mem}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001542 static constexpr const char* REG_TOKEN = "{reg}";
1543 static constexpr const char* REG1_TOKEN = "{reg1}";
1544 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -07001545 static constexpr const char* REG3_TOKEN = "{reg3}";
Lifang Xia60fdcb22023-03-15 13:36:40 +08001546 static constexpr const char* REG4_TOKEN = "{reg4}";
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
Vladimir Marko20a23082023-05-11 13:57:43 +00001568 ReplaceReg(REG_TOKEN, GetRegName<kRegView>(*reg), &base);
1569 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base);
Andreas Gampe851df202014-11-12 14:05:46 -08001570
Andreas Gampe851df202014-11-12 14:05:46 -08001571 str += base;
Vladimir Marko20a23082023-05-11 13:57:43 +00001572 str += "\n";
Andreas Gampe851df202014-11-12 14:05:46 -08001573 }
1574 }
Andreas Gampe851df202014-11-12 14:05:46 -08001575 return str;
1576 }
1577
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001578 // Override this to pad the code with NOPs to a certain size if needed.
Stefano Cianciulli78f3c722023-05-16 10:32:54 +00001579 virtual void Pad([[maybe_unused]] std::vector<uint8_t>& data) {}
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001580
Andreas Gampe2e965ac2016-11-03 17:24:15 -07001581 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +00001582 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001583 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -07001584 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001585 MemoryRegion code(&(*data)[0], data->size());
Nicolas Geoffray70bba9c2023-06-16 12:18:27 +01001586 assembler_->CopyInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07001587 Pad(*data);
David Srbeckyd6e14e02020-07-01 13:19:17 +01001588 Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001589 }
1590
Andreas Gampe849cc5e2014-11-18 13:46:46 -08001591 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -08001592
David Sehr3215fff2018-04-03 17:10:12 -07001593 MallocArenaPool pool_;
Vladimir Marko69d310e2017-10-09 14:12:23 +01001594 std::unique_ptr<ArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -07001595 std::unique_ptr<Ass> assembler_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -07001596
Andreas Gampe851df202014-11-12 14:05:46 -08001597 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001598};
1599
1600} // namespace art
1601
1602#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_