1 /* 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 22 #include <sys/stat.h> 23 24 #include <cstdio> 25 #include <cstdlib> 26 #include <fstream> 27 #include <iterator> 28 29 #include "base/array_ref.h" 30 #include "base/macros.h" 31 #include "base/malloc_arena_pool.h" 32 #include "assembler_test_base.h" 33 #include "common_runtime_test.h" // For ScratchFile 34 35 namespace art HIDDEN { 36 37 // Helper for a constexpr string length. 38 constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) { 39 return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1); 40 } 41 42 enum class RegisterView { // private 43 kUsePrimaryName, 44 kUseSecondaryName, 45 kUseTertiaryName, 46 kUseQuaternaryName, 47 }; 48 49 // For use in the template as the default type to get a nonvector registers version. 50 struct NoVectorRegs {}; 51 52 template<typename Ass, 53 typename Addr, 54 typename Reg, 55 typename FPReg, 56 typename Imm, 57 typename VecReg = NoVectorRegs> 58 class AssemblerTest : public AssemblerTestBase { 59 public: GetAssembler()60 Ass* GetAssembler() { 61 return assembler_.get(); 62 } 63 64 using TestFn = std::string (*)(AssemblerTest *, Ass *); 65 DriverFn(TestFn f,const std::string & test_name)66 void DriverFn(TestFn f, const std::string& test_name) { 67 DriverWrapper(f(this, assembler_.get()), test_name); 68 } 69 70 // This driver assumes the assembler has already been called. DriverStr(const std::string & assembly_string,const std::string & test_name)71 void DriverStr(const std::string& assembly_string, const std::string& test_name) { 72 DriverWrapper(assembly_string, test_name); 73 } 74 75 // 76 // Register repeats. 77 // 78 RepeatR(void (Ass::* f)(Reg),const std::string & fmt)79 std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) { 80 return RepeatTemplatedRegister<Reg>(f, 81 GetRegisters(), 82 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 83 fmt); 84 } 85 Repeatr(void (Ass::* f)(Reg),const std::string & fmt)86 std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) { 87 return RepeatTemplatedRegister<Reg>(f, 88 GetRegisters(), 89 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 90 fmt); 91 } 92 93 std::string RepeatRR(void (Ass::*f)(Reg, Reg), 94 const std::string& fmt, 95 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 96 return RepeatTemplatedRegisters<Reg, Reg>(f, 97 GetRegisters(), 98 GetRegisters(), 99 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 100 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 101 fmt, 102 except); 103 } 104 RepeatRRNoDupes(void (Ass::* f)(Reg,Reg),const std::string & fmt)105 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) { 106 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f, 107 GetRegisters(), 108 GetRegisters(), 109 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 110 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 111 fmt); 112 } 113 114 std::string Repeatrr(void (Ass::*f)(Reg, Reg), 115 const std::string& fmt, 116 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 117 return RepeatTemplatedRegisters<Reg, Reg>(f, 118 GetRegisters(), 119 GetRegisters(), 120 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 121 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 122 fmt, 123 except); 124 } 125 126 std::string Repeatww(void (Ass::*f)(Reg, Reg), 127 const std::string& fmt, 128 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 129 return RepeatTemplatedRegisters<Reg, Reg>(f, 130 GetRegisters(), 131 GetRegisters(), 132 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, 133 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, 134 fmt, 135 except); 136 } 137 138 std::string Repeatbb(void (Ass::*f)(Reg, Reg), 139 const std::string& fmt, 140 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 141 return RepeatTemplatedRegisters<Reg, Reg>(f, 142 GetRegisters(), 143 GetRegisters(), 144 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, 145 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, 146 fmt, 147 except); 148 } 149 RepeatRRR(void (Ass::* f)(Reg,Reg,Reg),const std::string & fmt)150 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) { 151 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f, 152 GetRegisters(), 153 GetRegisters(), 154 GetRegisters(), 155 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 156 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 157 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 158 fmt); 159 } 160 161 std::string Repeatrb(void (Ass::*f)(Reg, Reg), 162 const std::string& fmt, 163 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 164 return RepeatTemplatedRegisters<Reg, Reg>(f, 165 GetRegisters(), 166 GetRegisters(), 167 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 168 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, 169 fmt, 170 except); 171 } 172 173 std::string RepeatRr(void (Ass::*f)(Reg, Reg), 174 const std::string& fmt, 175 const std::vector<std::pair<Reg, Reg>>* except = nullptr) { 176 return RepeatTemplatedRegisters<Reg, Reg>(f, 177 GetRegisters(), 178 GetRegisters(), 179 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 180 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 181 fmt, 182 except); 183 } 184 RepeatRI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)185 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { 186 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt); 187 } 188 RepeatrI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)189 std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { 190 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt); 191 } 192 RepeatwI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)193 std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { 194 return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt); 195 } 196 RepeatbI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)197 std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) { 198 return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt); 199 } 200 201 template <typename Reg1, typename Reg2, typename ImmType> 202 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType), 203 int imm_bits, 204 ArrayRef<const Reg1> reg1_registers, 205 ArrayRef<const Reg2> reg2_registers, 206 std::string (AssemblerTest::*GetName1)(const Reg1&), 207 std::string (AssemblerTest::*GetName2)(const Reg2&), 208 const std::string& fmt, 209 int bias = 0, 210 int multiplier = 1) { 211 std::string str; 212 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0)); 213 214 for (auto reg1 : reg1_registers) { 215 for (auto reg2 : reg2_registers) { 216 for (int64_t imm : imms) { 217 ImmType new_imm = CreateImmediate(imm); 218 if (f != nullptr) { 219 (assembler_.get()->*f)(reg1, reg2, new_imm * multiplier + bias); 220 } 221 std::string base = fmt; 222 223 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 224 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 225 ReplaceImm(imm, bias, multiplier, &base); 226 227 str += base; 228 str += "\n"; 229 } 230 } 231 } 232 return str; 233 } 234 235 template <typename Reg1, typename Reg2, typename Reg3, typename ImmType> RepeatTemplatedRegistersImmBits(void (Ass::* f)(Reg1,Reg2,Reg3,ImmType),int imm_bits,ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),const std::string & fmt,int bias)236 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType), 237 int imm_bits, 238 ArrayRef<const Reg1> reg1_registers, 239 ArrayRef<const Reg2> reg2_registers, 240 ArrayRef<const Reg3> reg3_registers, 241 std::string (AssemblerTest::*GetName1)(const Reg1&), 242 std::string (AssemblerTest::*GetName2)(const Reg2&), 243 std::string (AssemblerTest::*GetName3)(const Reg3&), 244 const std::string& fmt, 245 int bias) { 246 std::string str; 247 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0)); 248 249 for (auto reg1 : reg1_registers) { 250 for (auto reg2 : reg2_registers) { 251 for (auto reg3 : reg3_registers) { 252 for (int64_t imm : imms) { 253 ImmType new_imm = CreateImmediate(imm); 254 if (f != nullptr) { 255 (assembler_.get()->*f)(reg1, reg2, reg3, new_imm + bias); 256 } 257 std::string base = fmt; 258 259 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 260 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 261 ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base); 262 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base); 263 264 str += base; 265 str += "\n"; 266 } 267 } 268 } 269 } 270 return str; 271 } 272 273 template <typename ImmType, typename Reg1, typename Reg2> RepeatTemplatedImmBitsRegisters(void (Ass::* f)(ImmType,Reg1,Reg2),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),int imm_bits,const std::string & fmt)274 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2), 275 ArrayRef<const Reg1> reg1_registers, 276 ArrayRef<const Reg2> reg2_registers, 277 std::string (AssemblerTest::*GetName1)(const Reg1&), 278 std::string (AssemblerTest::*GetName2)(const Reg2&), 279 int imm_bits, 280 const std::string& fmt) { 281 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0)); 282 283 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size()); 284 285 std::string str; 286 for (auto reg1 : reg1_registers) { 287 for (auto reg2 : reg2_registers) { 288 for (int64_t imm : imms) { 289 ImmType new_imm = CreateImmediate(imm); 290 if (f != nullptr) { 291 (assembler_.get()->*f)(new_imm, reg1, reg2); 292 } 293 std::string base = fmt; 294 295 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 296 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 297 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base); 298 299 str += base; 300 str += "\n"; 301 } 302 } 303 } 304 return str; 305 } 306 307 template <typename RegType, typename ImmType> RepeatTemplatedRegisterImmBits(void (Ass::* f)(RegType,ImmType),int imm_bits,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt,int bias)308 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType), 309 int imm_bits, 310 ArrayRef<const RegType> registers, 311 std::string (AssemblerTest::*GetName)(const RegType&), 312 const std::string& fmt, 313 int bias) { 314 std::string str; 315 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0)); 316 317 for (auto reg : registers) { 318 for (int64_t imm : imms) { 319 ImmType new_imm = CreateImmediate(imm); 320 if (f != nullptr) { 321 (assembler_.get()->*f)(reg, new_imm + bias); 322 } 323 std::string base = fmt; 324 325 ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base); 326 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base); 327 328 str += base; 329 str += "\n"; 330 } 331 } 332 return str; 333 } 334 335 template <typename RegType, typename ImmType> RepeatTemplatedRegisterImmBitsShift(void (Ass::* f)(RegType,ImmType),int imm_bits,int shift,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt,int bias)336 std::string RepeatTemplatedRegisterImmBitsShift( 337 void (Ass::*f)(RegType, ImmType), 338 int imm_bits, 339 int shift, 340 ArrayRef<const RegType> registers, 341 std::string (AssemblerTest::*GetName)(const RegType&), 342 const std::string& fmt, 343 int bias) { 344 std::string str; 345 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift); 346 347 for (auto reg : registers) { 348 for (int64_t imm : imms) { 349 ImmType new_imm = CreateImmediate(imm); 350 if (f != nullptr) { 351 (assembler_.get()->*f)(reg, new_imm + bias); 352 } 353 std::string base = fmt; 354 355 ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base); 356 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base); 357 358 str += base; 359 str += "\n"; 360 } 361 } 362 return str; 363 } 364 365 template <typename ImmType> 366 std::string RepeatTemplatedImmBitsShift( 367 void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) { 368 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift); 369 370 WarnOnCombinations(imms.size()); 371 372 std::string str; 373 374 for (int64_t imm : imms) { 375 ImmType new_imm = CreateImmediate(imm); 376 if (f != nullptr) { 377 (assembler_.get()->*f)(new_imm + bias); 378 } 379 std::string base = fmt; 380 381 ReplaceImm(imm, bias, /*multiplier=*/ 1, &base); 382 383 str += base; 384 str += "\n"; 385 } 386 return str; 387 } 388 389 template <typename Reg1, typename Reg2, typename ImmType> 390 std::string RepeatTemplatedRegistersImmBitsShift( 391 void (Ass::*f)(Reg1, Reg2, ImmType), 392 int imm_bits, 393 int shift, 394 ArrayRef<const Reg1> reg1_registers, 395 ArrayRef<const Reg2> reg2_registers, 396 std::string (AssemblerTest::*GetName1)(const Reg1&), 397 std::string (AssemblerTest::*GetName2)(const Reg2&), 398 const std::string& fmt, 399 int bias = 0, 400 int multiplier = 1) { 401 std::string str; 402 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0), shift); 403 404 for (auto reg1 : reg1_registers) { 405 for (auto reg2 : reg2_registers) { 406 for (int64_t imm : imms) { 407 ImmType new_imm = CreateImmediate(imm); 408 if (f != nullptr) { 409 (assembler_.get()->*f)(reg1, reg2, new_imm * multiplier + bias); 410 } 411 std::string base = fmt; 412 413 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 414 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 415 ReplaceImm(imm, bias, multiplier, &base); 416 417 str += base; 418 str += "\n"; 419 } 420 } 421 } 422 return str; 423 } 424 425 template <typename ImmType> 426 std::string RepeatIbS( 427 void (Ass::*f)(ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) { 428 return RepeatTemplatedImmBitsShift<ImmType>(f, imm_bits, shift, fmt, bias); 429 } 430 431 template <typename ImmType> 432 std::string RepeatRIbS( 433 void (Ass::*f)(Reg, ImmType), int imm_bits, int shift, const std::string& fmt, int bias = 0) { 434 return RepeatTemplatedRegisterImmBitsShift<Reg, ImmType>( 435 f, 436 imm_bits, 437 shift, 438 GetRegisters(), 439 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 440 fmt, 441 bias); 442 } 443 444 template <typename ImmType> 445 std::string RepeatRRIbS(void (Ass::*f)(Reg, Reg, ImmType), 446 int imm_bits, 447 int shift, 448 const std::string& fmt, 449 int bias = 0) { 450 return RepeatTemplatedRegistersImmBitsShift<Reg, Reg, ImmType>( 451 f, 452 imm_bits, 453 shift, 454 GetRegisters(), 455 GetRegisters(), 456 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 457 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 458 fmt, 459 bias); 460 } 461 462 template <typename ImmType> 463 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType), 464 int imm_bits, 465 const std::string& fmt, 466 int bias = 0) { 467 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f, 468 imm_bits, 469 GetRegisters(), 470 GetRegisters(), 471 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 472 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 473 fmt, 474 bias); 475 } 476 477 template <typename ImmType> 478 std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType), 479 int imm_bits, 480 const std::string& fmt, 481 int bias = 0) { 482 return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f, 483 imm_bits, 484 GetRegisters(), 485 GetRegisters(), 486 GetRegisters(), 487 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 488 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 489 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 490 fmt, 491 bias); 492 } 493 494 template <typename ImmType> 495 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) { 496 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f, 497 imm_bits, 498 GetRegisters(), 499 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 500 fmt, 501 bias); 502 } 503 504 template <typename ImmType> 505 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType), 506 int imm_bits, 507 const std::string& fmt, 508 int bias = 0) { 509 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f, 510 imm_bits, 511 GetFPRegisters(), 512 GetRegisters(), 513 &AssemblerTest::GetFPRegName, 514 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 515 fmt, 516 bias); 517 } 518 RepeatFF(void (Ass::* f)(FPReg,FPReg),const std::string & fmt)519 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) { 520 return RepeatTemplatedRegisters<FPReg, FPReg>(f, 521 GetFPRegisters(), 522 GetFPRegisters(), 523 &AssemblerTest::GetFPRegName, 524 &AssemblerTest::GetFPRegName, 525 fmt); 526 } 527 RepeatFFF(void (Ass::* f)(FPReg,FPReg,FPReg),const std::string & fmt)528 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) { 529 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f, 530 GetFPRegisters(), 531 GetFPRegisters(), 532 GetFPRegisters(), 533 &AssemblerTest::GetFPRegName, 534 &AssemblerTest::GetFPRegName, 535 &AssemblerTest::GetFPRegName, 536 fmt); 537 } 538 RepeatFFFF(void (Ass::* f)(FPReg,FPReg,FPReg,FPReg),const std::string & fmt)539 std::string RepeatFFFF(void (Ass::*f)(FPReg, FPReg, FPReg, FPReg), const std::string& fmt) { 540 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg, FPReg>(f, 541 GetFPRegisters(), 542 GetFPRegisters(), 543 GetFPRegisters(), 544 GetFPRegisters(), 545 &AssemblerTest::GetFPRegName, 546 &AssemblerTest::GetFPRegName, 547 &AssemblerTest::GetFPRegName, 548 &AssemblerTest::GetFPRegName, 549 fmt); 550 } 551 RepeatFFR(void (Ass::* f)(FPReg,FPReg,Reg),const std::string & fmt)552 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) { 553 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>( 554 f, 555 GetFPRegisters(), 556 GetFPRegisters(), 557 GetRegisters(), 558 &AssemblerTest::GetFPRegName, 559 &AssemblerTest::GetFPRegName, 560 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 561 fmt); 562 } 563 RepeatFFI(void (Ass::* f)(FPReg,FPReg,const Imm &),size_t imm_bytes,const std::string & fmt)564 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&), 565 size_t imm_bytes, 566 const std::string& fmt) { 567 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f, 568 GetFPRegisters(), 569 GetFPRegisters(), 570 &AssemblerTest::GetFPRegName, 571 &AssemblerTest::GetFPRegName, 572 imm_bytes, 573 fmt); 574 } 575 576 template <typename ImmType> RepeatFFIb(void (Ass::* f)(FPReg,FPReg,ImmType),int imm_bits,const std::string & fmt)577 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType), 578 int imm_bits, 579 const std::string& fmt) { 580 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f, 581 imm_bits, 582 GetFPRegisters(), 583 GetFPRegisters(), 584 &AssemblerTest::GetFPRegName, 585 &AssemblerTest::GetFPRegName, 586 fmt); 587 } 588 589 template <typename ImmType> RepeatIbFF(void (Ass::* f)(ImmType,FPReg,FPReg),int imm_bits,const std::string & fmt)590 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg), 591 int imm_bits, 592 const std::string& fmt) { 593 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f, 594 GetFPRegisters(), 595 GetFPRegisters(), 596 &AssemblerTest::GetFPRegName, 597 &AssemblerTest::GetFPRegName, 598 imm_bits, 599 fmt); 600 } 601 RepeatRFF(void (Ass::* f)(Reg,FPReg,FPReg),const std::string & fmt)602 std::string RepeatRFF(void (Ass::*f)(Reg, FPReg, FPReg), const std::string& fmt) { 603 return RepeatTemplatedRegisters<Reg, FPReg, FPReg>( 604 f, 605 GetRegisters(), 606 GetFPRegisters(), 607 GetFPRegisters(), 608 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 609 &AssemblerTest::GetFPRegName, 610 &AssemblerTest::GetFPRegName, 611 fmt); 612 } 613 614 template <typename ImmType> RepeatRFIb(void (Ass::* f)(Reg,FPReg,ImmType),int imm_bits,const std::string & fmt)615 std::string RepeatRFIb(void (Ass::*f)(Reg, FPReg, ImmType), 616 int imm_bits, 617 const std::string& fmt) { 618 return RepeatTemplatedRegistersImmBits<Reg, FPReg, ImmType>( 619 f, 620 imm_bits, 621 GetRegisters(), 622 GetFPRegisters(), 623 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 624 &AssemblerTest::GetFPRegName, 625 fmt); 626 } 627 RepeatFR(void (Ass::* f)(FPReg,Reg),const std::string & fmt)628 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) { 629 return RepeatTemplatedRegisters<FPReg, Reg>(f, 630 GetFPRegisters(), 631 GetRegisters(), 632 &AssemblerTest::GetFPRegName, 633 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 634 fmt); 635 } 636 RepeatFr(void (Ass::* f)(FPReg,Reg),const std::string & fmt)637 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) { 638 return RepeatTemplatedRegisters<FPReg, Reg>(f, 639 GetFPRegisters(), 640 GetRegisters(), 641 &AssemblerTest::GetFPRegName, 642 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 643 fmt); 644 } 645 RepeatRF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)646 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) { 647 return RepeatTemplatedRegisters<Reg, FPReg>(f, 648 GetRegisters(), 649 GetFPRegisters(), 650 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 651 &AssemblerTest::GetFPRegName, 652 fmt); 653 } 654 RepeatrF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)655 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) { 656 return RepeatTemplatedRegisters<Reg, FPReg>(f, 657 GetRegisters(), 658 GetFPRegisters(), 659 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 660 &AssemblerTest::GetFPRegName, 661 fmt); 662 } 663 664 std::string RepeatI(void (Ass::*f)(const Imm&), 665 size_t imm_bytes, 666 const std::string& fmt, 667 bool as_uint = false) { 668 std::string str; 669 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint); 670 671 WarnOnCombinations(imms.size()); 672 673 for (int64_t imm : imms) { 674 Imm new_imm = CreateImmediate(imm); 675 if (f != nullptr) { 676 (assembler_.get()->*f)(new_imm); 677 } 678 std::string base = fmt; 679 680 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base); 681 682 str += base; 683 str += "\n"; 684 } 685 return str; 686 } 687 RepeatV(void (Ass::* f)(VecReg),const std::string & fmt)688 std::string RepeatV(void (Ass::*f)(VecReg), const std::string& fmt) { 689 return RepeatTemplatedRegister<VecReg>( 690 f, GetVectorRegisters(), &AssemblerTest::GetVecRegName, fmt); 691 } 692 RepeatVV(void (Ass::* f)(VecReg,VecReg),const std::string & fmt)693 std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) { 694 return RepeatTemplatedRegisters<VecReg, VecReg>(f, 695 GetVectorRegisters(), 696 GetVectorRegisters(), 697 &AssemblerTest::GetVecRegName, 698 &AssemblerTest::GetVecRegName, 699 fmt); 700 } 701 RepeatVVV(void (Ass::* f)(VecReg,VecReg,VecReg),const std::string & fmt)702 std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) { 703 return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f, 704 GetVectorRegisters(), 705 GetVectorRegisters(), 706 GetVectorRegisters(), 707 &AssemblerTest::GetVecRegName, 708 &AssemblerTest::GetVecRegName, 709 &AssemblerTest::GetVecRegName, 710 fmt); 711 } 712 RepeatVVR(void (Ass::* f)(VecReg,VecReg,Reg),const std::string & fmt)713 std::string RepeatVVR(void (Ass::*f)(VecReg, VecReg, Reg), const std::string& fmt) { 714 return RepeatTemplatedRegisters<VecReg, VecReg, Reg>( 715 f, 716 GetVectorRegisters(), 717 GetVectorRegisters(), 718 GetRegisters(), 719 &AssemblerTest::GetVecRegName, 720 &AssemblerTest::GetVecRegName, 721 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 722 fmt); 723 } 724 RepeatVR(void (Ass::* f)(VecReg,Reg),const std::string & fmt)725 std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) { 726 return RepeatTemplatedRegisters<VecReg, Reg>( 727 f, 728 GetVectorRegisters(), 729 GetRegisters(), 730 &AssemblerTest::GetVecRegName, 731 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 732 fmt); 733 } 734 RepeatVF(void (Ass::* f)(VecReg,FPReg),const std::string & fmt)735 std::string RepeatVF(void (Ass::*f)(VecReg, FPReg), const std::string& fmt) { 736 return RepeatTemplatedRegisters<VecReg, FPReg>(f, 737 GetVectorRegisters(), 738 GetFPRegisters(), 739 &AssemblerTest::GetVecRegName, 740 &AssemblerTest::GetFPRegName, 741 fmt); 742 } 743 RepeatFV(void (Ass::* f)(FPReg,VecReg),const std::string & fmt)744 std::string RepeatFV(void (Ass::*f)(FPReg, VecReg), const std::string& fmt) { 745 return RepeatTemplatedRegisters<FPReg, VecReg>(f, 746 GetFPRegisters(), 747 GetVectorRegisters(), 748 &AssemblerTest::GetFPRegName, 749 &AssemblerTest::GetVecRegName, 750 fmt); 751 } 752 RepeatRV(void (Ass::* f)(Reg,VecReg),const std::string & fmt)753 std::string RepeatRV(void (Ass::*f)(Reg, VecReg), const std::string& fmt) { 754 return RepeatTemplatedRegisters<Reg, VecReg>( 755 f, 756 GetRegisters(), 757 GetVectorRegisters(), 758 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 759 &AssemblerTest::GetVecRegName, 760 fmt); 761 } 762 763 template <typename ImmType> 764 std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType), 765 int imm_bits, 766 std::string fmt, 767 int bias = 0) { 768 return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f, 769 imm_bits, 770 GetVectorRegisters(), 771 &AssemblerTest::GetVecRegName, 772 fmt, 773 bias); 774 } 775 776 template <typename ImmType> 777 std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType), 778 int imm_bits, 779 const std::string& fmt, 780 int bias = 0, 781 int multiplier = 1) { 782 return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>( 783 f, 784 imm_bits, 785 GetVectorRegisters(), 786 GetRegisters(), 787 &AssemblerTest::GetVecRegName, 788 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 789 fmt, 790 bias, 791 multiplier); 792 } 793 794 template <typename ImmType> 795 std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType), 796 int imm_bits, 797 const std::string& fmt, 798 int bias = 0, 799 int multiplier = 1) { 800 return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>( 801 f, 802 imm_bits, 803 GetRegisters(), 804 GetVectorRegisters(), 805 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 806 &AssemblerTest::GetVecRegName, 807 fmt, 808 bias, 809 multiplier); 810 } 811 812 template <typename ImmType> 813 std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType), 814 int imm_bits, 815 const std::string& fmt, 816 int bias = 0) { 817 return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f, 818 imm_bits, 819 GetVectorRegisters(), 820 GetVectorRegisters(), 821 &AssemblerTest::GetVecRegName, 822 &AssemblerTest::GetVecRegName, 823 fmt, 824 bias); 825 } 826 827 // The following functions are public so that TestFn can use them... 828 829 // Returns a vector of address used by any of the repeat methods 830 // involving an "A" (e.g. RepeatA). 831 virtual std::vector<Addr> GetAddresses() = 0; 832 833 // Returns a vector of registers used by any of the repeat methods 834 // involving an "R" (e.g. RepeatR). 835 virtual ArrayRef<const Reg> GetRegisters() = 0; 836 837 // Returns a vector of fp-registers used by any of the repeat methods 838 // involving an "F" (e.g. RepeatFF). GetFPRegisters()839 virtual ArrayRef<const FPReg> GetFPRegisters() { 840 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers"; 841 UNREACHABLE(); 842 } 843 844 // Returns a vector of dedicated simd-registers used by any of the repeat 845 // methods involving an "V" (e.g. RepeatVV). GetVectorRegisters()846 virtual ArrayRef<const VecReg> GetVectorRegisters() { 847 UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers"; 848 UNREACHABLE(); 849 } 850 851 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems. GetSecondaryRegisterName(const Reg & reg)852 virtual std::string GetSecondaryRegisterName([[maybe_unused]] const Reg& reg) { 853 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers"; 854 UNREACHABLE(); 855 } 856 857 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems. GetTertiaryRegisterName(const Reg & reg)858 virtual std::string GetTertiaryRegisterName([[maybe_unused]] const Reg& reg) { 859 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers"; 860 UNREACHABLE(); 861 } 862 863 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems. GetQuaternaryRegisterName(const Reg & reg)864 virtual std::string GetQuaternaryRegisterName([[maybe_unused]] const Reg& reg) { 865 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers"; 866 UNREACHABLE(); 867 } 868 GetRegisterName(const Reg & reg)869 std::string GetRegisterName(const Reg& reg) { 870 return GetRegName<RegisterView::kUsePrimaryName>(reg); 871 } 872 873 protected: AssemblerTest()874 AssemblerTest() {} 875 SetUp()876 void SetUp() override { 877 AssemblerTestBase::SetUp(); 878 allocator_.reset(new ArenaAllocator(&pool_)); 879 assembler_.reset(CreateAssembler(allocator_.get())); 880 SetUpHelpers(); 881 } 882 TearDown()883 void TearDown() override { 884 AssemblerTestBase::TearDown(); 885 assembler_.reset(); 886 allocator_.reset(); 887 } 888 889 // Override this to set up any architecture-specific things, e.g., CPU revision. CreateAssembler(ArenaAllocator * allocator)890 virtual Ass* CreateAssembler(ArenaAllocator* allocator) { 891 return new (allocator) Ass(allocator); 892 } 893 894 // Override this to set up any architecture-specific things, e.g., register vectors. SetUpHelpers()895 virtual void SetUpHelpers() {} 896 897 // Create a couple of immediate values up to the number of bytes given. 898 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) { 899 std::vector<int64_t> res; 900 res.push_back(0); 901 if (!as_uint) { 902 res.push_back(-1); 903 } else { 904 res.push_back(0xFF); 905 } 906 res.push_back(0x12); 907 if (imm_bytes >= 2) { 908 res.push_back(0x1234); 909 if (!as_uint) { 910 res.push_back(-0x1234); 911 } else { 912 res.push_back(0xFFFF); 913 } 914 if (imm_bytes >= 4) { 915 res.push_back(0x12345678); 916 if (!as_uint) { 917 res.push_back(-0x12345678); 918 } else { 919 res.push_back(0xFFFFFFFF); 920 } 921 if (imm_bytes >= 6) { 922 res.push_back(0x123456789ABC); 923 if (!as_uint) { 924 res.push_back(-0x123456789ABC); 925 } 926 if (imm_bytes >= 8) { 927 res.push_back(0x123456789ABCDEF0); 928 if (!as_uint) { 929 res.push_back(-0x123456789ABCDEF0); 930 } else { 931 res.push_back(0xFFFFFFFFFFFFFFFF); 932 } 933 } 934 } 935 } 936 } 937 return res; 938 } 939 940 const int kMaxBitsExhaustiveTest = 8; 941 942 // Create a couple of immediate values up to the number of bits given. 943 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, 944 bool as_uint = false, 945 int shift = 0) { 946 CHECK_GT(imm_bits, 0); 947 CHECK_LE(imm_bits, 64); 948 std::vector<int64_t> res; 949 950 if (imm_bits <= kMaxBitsExhaustiveTest) { 951 if (as_uint) { 952 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) { 953 res.push_back(static_cast<int64_t>(i << shift)); 954 } 955 } else { 956 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) { 957 res.push_back(i << shift); 958 } 959 } 960 } else { 961 if (as_uint) { 962 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest); 963 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest); 964 i++) { 965 res.push_back(static_cast<int64_t>(i << shift)); 966 } 967 for (int i = 0; i <= imm_bits; i++) { 968 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) + 969 ((MaxInt<uint64_t>(imm_bits) - 970 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1)) 971 * i / imm_bits); 972 res.push_back(static_cast<int64_t>(j << shift)); 973 } 974 } else { 975 for (int i = 0; i <= imm_bits; i++) { 976 int64_t j = MinInt<int64_t>(imm_bits) + 977 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) - 978 MinInt<int64_t>(imm_bits)) 979 * i) / imm_bits); 980 res.push_back(static_cast<int64_t>(j << shift)); 981 } 982 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest); 983 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest); 984 i++) { 985 res.push_back(static_cast<int64_t>(i << shift)); 986 } 987 for (int i = 0; i <= imm_bits; i++) { 988 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) + 989 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1)) 990 * i / imm_bits); 991 res.push_back(static_cast<int64_t>(j << shift)); 992 } 993 } 994 } 995 996 return res; 997 } 998 999 // Create an immediate from the specific value. 1000 virtual Imm CreateImmediate(int64_t imm_value) = 0; 1001 1002 // 1003 // Addresses repeats. 1004 // 1005 1006 // Repeats over addresses provided by fixture. RepeatA(void (Ass::* f)(const Addr &),const std::string & fmt)1007 std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) { 1008 return RepeatA(f, GetAddresses(), fmt); 1009 } 1010 1011 // Variant that takes explicit vector of addresss 1012 // (to test restricted addressing modes set). RepeatA(void (Ass::* f)(const Addr &),const std::vector<Addr> & a,const std::string & fmt)1013 std::string RepeatA(void (Ass::*f)(const Addr&), 1014 const std::vector<Addr>& a, 1015 const std::string& fmt) { 1016 return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt); 1017 } 1018 1019 // Repeats over addresses and immediates provided by fixture. RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::string & fmt)1020 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&), 1021 size_t imm_bytes, 1022 const std::string& fmt) { 1023 return RepeatAI(f, imm_bytes, GetAddresses(), fmt); 1024 } 1025 1026 // Variant that takes explicit vector of addresss 1027 // (to test restricted addressing modes set). RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::vector<Addr> & a,const std::string & fmt)1028 std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&), 1029 size_t imm_bytes, 1030 const std::vector<Addr>& a, 1031 const std::string& fmt) { 1032 return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt); 1033 } 1034 1035 // Repeats over registers and addresses provided by fixture. RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1036 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { 1037 return RepeatRA(f, GetAddresses(), fmt); 1038 } 1039 1040 // Variant that takes explicit vector of addresss 1041 // (to test restricted addressing modes set). RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1042 std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), 1043 const std::vector<Addr>& a, 1044 const std::string& fmt) { 1045 return RepeatTemplatedRegMem<Reg, Addr>( 1046 f, 1047 GetRegisters(), 1048 a, 1049 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 1050 &AssemblerTest::GetAddrName, 1051 fmt); 1052 } 1053 1054 // Repeats over secondary registers and addresses provided by fixture. RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1055 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { 1056 return RepeatrA(f, GetAddresses(), fmt); 1057 } 1058 1059 // Variant that takes explicit vector of addresss 1060 // (to test restricted addressing modes set). RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1061 std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), 1062 const std::vector<Addr>& a, 1063 const std::string& fmt) { 1064 return RepeatTemplatedRegMem<Reg, Addr>( 1065 f, 1066 GetRegisters(), 1067 a, 1068 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 1069 &AssemblerTest::GetAddrName, 1070 fmt); 1071 } 1072 1073 // Repeats over tertiary registers and addresses provided by fixture. RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1074 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { 1075 return RepeatwA(f, GetAddresses(), fmt); 1076 } 1077 1078 // Variant that takes explicit vector of addresss 1079 // (to test restricted addressing modes set). RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1080 std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), 1081 const std::vector<Addr>& a, 1082 const std::string& fmt) { 1083 return RepeatTemplatedRegMem<Reg, Addr>( 1084 f, 1085 GetRegisters(), 1086 a, 1087 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, 1088 &AssemblerTest::GetAddrName, 1089 fmt); 1090 } 1091 1092 // Repeats over quaternary registers and addresses provided by fixture. RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)1093 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) { 1094 return RepeatbA(f, GetAddresses(), fmt); 1095 } 1096 1097 // Variant that takes explicit vector of addresss 1098 // (to test restricted addressing modes set). RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1099 std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), 1100 const std::vector<Addr>& a, 1101 const std::string& fmt) { 1102 return RepeatTemplatedRegMem<Reg, Addr>( 1103 f, 1104 GetRegisters(), 1105 a, 1106 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, 1107 &AssemblerTest::GetAddrName, 1108 fmt); 1109 } 1110 1111 // Repeats over fp-registers and addresses provided by fixture. RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::string & fmt)1112 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) { 1113 return RepeatFA(f, GetAddresses(), fmt); 1114 } 1115 1116 // Variant that takes explicit vector of addresss 1117 // (to test restricted addressing modes set). RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1118 std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), 1119 const std::vector<Addr>& a, 1120 const std::string& fmt) { 1121 return RepeatTemplatedRegMem<FPReg, Addr>( 1122 f, 1123 GetFPRegisters(), 1124 a, 1125 &AssemblerTest::GetFPRegName, 1126 &AssemblerTest::GetAddrName, 1127 fmt); 1128 } 1129 1130 // Repeats over addresses and registers provided by fixture. RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1131 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { 1132 return RepeatAR(f, GetAddresses(), fmt); 1133 } 1134 1135 // Variant that takes explicit vector of addresss 1136 // (to test restricted addressing modes set). RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1137 std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), 1138 const std::vector<Addr>& a, 1139 const std::string& fmt) { 1140 return RepeatTemplatedMemReg<Addr, Reg>( 1141 f, 1142 a, 1143 GetRegisters(), 1144 &AssemblerTest::GetAddrName, 1145 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, 1146 fmt); 1147 } 1148 1149 // Repeats over addresses and secondary registers provided by fixture. RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1150 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { 1151 return RepeatAr(f, GetAddresses(), fmt); 1152 } 1153 1154 // Variant that takes explicit vector of addresss 1155 // (to test restricted addressing modes set). RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1156 std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), 1157 const std::vector<Addr>& a, 1158 const std::string& fmt) { 1159 return RepeatTemplatedMemReg<Addr, Reg>( 1160 f, 1161 a, 1162 GetRegisters(), 1163 &AssemblerTest::GetAddrName, 1164 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>, 1165 fmt); 1166 } 1167 1168 // Repeats over addresses and tertiary registers provided by fixture. RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1169 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { 1170 return RepeatAw(f, GetAddresses(), fmt); 1171 } 1172 1173 // Variant that takes explicit vector of addresss 1174 // (to test restricted addressing modes set). RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1175 std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), 1176 const std::vector<Addr>& a, 1177 const std::string& fmt) { 1178 return RepeatTemplatedMemReg<Addr, Reg>( 1179 f, 1180 a, 1181 GetRegisters(), 1182 &AssemblerTest::GetAddrName, 1183 &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>, 1184 fmt); 1185 } 1186 1187 // Repeats over addresses and quaternary registers provided by fixture. RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1188 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) { 1189 return RepeatAb(f, GetAddresses(), fmt); 1190 } 1191 1192 // Variant that takes explicit vector of addresss 1193 // (to test restricted addressing modes set). RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1194 std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), 1195 const std::vector<Addr>& a, 1196 const std::string& fmt) { 1197 return RepeatTemplatedMemReg<Addr, Reg>( 1198 f, 1199 a, 1200 GetRegisters(), 1201 &AssemblerTest::GetAddrName, 1202 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>, 1203 fmt); 1204 } 1205 1206 // Repeats over addresses and fp-registers provided by fixture. RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::string & fmt)1207 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) { 1208 return RepeatAF(f, GetAddresses(), fmt); 1209 } 1210 1211 // Variant that takes explicit vector of addresss 1212 // (to test restricted addressing modes set). RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::vector<Addr> & a,const std::string & fmt)1213 std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), 1214 const std::vector<Addr>& a, 1215 const std::string& fmt) { 1216 return RepeatTemplatedMemReg<Addr, FPReg>( 1217 f, 1218 a, 1219 GetFPRegisters(), 1220 &AssemblerTest::GetAddrName, 1221 &AssemblerTest::GetFPRegName, 1222 fmt); 1223 } 1224 1225 template <typename AddrType> RepeatTemplatedMem(void (Ass::* f)(const AddrType &),const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1226 std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&), 1227 const std::vector<AddrType> addresses, 1228 std::string (AssemblerTest::*GetAName)(const AddrType&), 1229 const std::string& fmt) { 1230 WarnOnCombinations(addresses.size()); 1231 std::string str; 1232 for (auto addr : addresses) { 1233 if (f != nullptr) { 1234 (assembler_.get()->*f)(addr); 1235 } 1236 std::string base = fmt; 1237 1238 ReplaceAddr((this->*GetAName)(addr), &base); 1239 1240 str += base; 1241 str += "\n"; 1242 } 1243 return str; 1244 } 1245 1246 template <typename AddrType> RepeatTemplatedMemImm(void (Ass::* f)(const AddrType &,const Imm &),size_t imm_bytes,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1247 std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&), 1248 size_t imm_bytes, 1249 const std::vector<AddrType> addresses, 1250 std::string (AssemblerTest::*GetAName)(const AddrType&), 1251 const std::string& fmt) { 1252 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes); 1253 WarnOnCombinations(addresses.size() * imms.size()); 1254 std::string str; 1255 for (auto addr : addresses) { 1256 for (int64_t imm : imms) { 1257 Imm new_imm = CreateImmediate(imm); 1258 if (f != nullptr) { 1259 (assembler_.get()->*f)(addr, new_imm); 1260 } 1261 std::string base = fmt; 1262 1263 ReplaceAddr((this->*GetAName)(addr), &base); 1264 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base); 1265 1266 str += base; 1267 str += "\n"; 1268 } 1269 } 1270 return str; 1271 } 1272 1273 template <typename RegType, typename AddrType> RepeatTemplatedRegMem(void (Ass::* f)(RegType,const AddrType &),ArrayRef<const RegType> registers,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetRName)(const RegType &),std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1274 std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&), 1275 ArrayRef<const RegType> registers, 1276 const std::vector<AddrType> addresses, 1277 std::string (AssemblerTest::*GetRName)(const RegType&), 1278 std::string (AssemblerTest::*GetAName)(const AddrType&), 1279 const std::string& fmt) { 1280 WarnOnCombinations(addresses.size() * registers.size()); 1281 std::string str; 1282 for (auto reg : registers) { 1283 for (auto addr : addresses) { 1284 if (f != nullptr) { 1285 (assembler_.get()->*f)(reg, addr); 1286 } 1287 std::string base = fmt; 1288 1289 ReplaceReg(REG_TOKEN, (this->*GetRName)(reg), &base); 1290 ReplaceAddr((this->*GetAName)(addr), &base); 1291 1292 str += base; 1293 str += "\n"; 1294 } 1295 } 1296 return str; 1297 } 1298 1299 template <typename AddrType, typename RegType> RepeatTemplatedMemReg(void (Ass::* f)(const AddrType &,RegType),const std::vector<AddrType> addresses,ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetAName)(const AddrType &),std::string (AssemblerTest::* GetRName)(const RegType &),const std::string & fmt)1300 std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType), 1301 const std::vector<AddrType> addresses, 1302 ArrayRef<const RegType> registers, 1303 std::string (AssemblerTest::*GetAName)(const AddrType&), 1304 std::string (AssemblerTest::*GetRName)(const RegType&), 1305 const std::string& fmt) { 1306 WarnOnCombinations(addresses.size() * registers.size()); 1307 std::string str; 1308 for (auto addr : addresses) { 1309 for (auto reg : registers) { 1310 if (f != nullptr) { 1311 (assembler_.get()->*f)(addr, reg); 1312 } 1313 std::string base = fmt; 1314 1315 ReplaceAddr((this->*GetAName)(addr), &base); 1316 ReplaceReg(REG_TOKEN, (this->*GetRName)(reg), &base); 1317 1318 str += base; 1319 str += "\n"; 1320 } 1321 } 1322 return str; 1323 } 1324 1325 // 1326 // Register repeats. 1327 // 1328 1329 template <typename RegType> RepeatTemplatedRegister(void (Ass::* f)(RegType),ArrayRef<const RegType> registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt)1330 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType), 1331 ArrayRef<const RegType> registers, 1332 std::string (AssemblerTest::*GetName)(const RegType&), 1333 const std::string& fmt) { 1334 std::string str; 1335 for (auto reg : registers) { 1336 if (f != nullptr) { 1337 (assembler_.get()->*f)(reg); 1338 } 1339 std::string base = fmt; 1340 1341 ReplaceReg(REG_TOKEN, (this->*GetName)(reg), &base); 1342 1343 str += base; 1344 str += "\n"; 1345 } 1346 return str; 1347 } 1348 1349 template <typename Reg1, typename Reg2> 1350 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2), 1351 ArrayRef<const Reg1> reg1_registers, 1352 ArrayRef<const Reg2> reg2_registers, 1353 std::string (AssemblerTest::*GetName1)(const Reg1&), 1354 std::string (AssemblerTest::*GetName2)(const Reg2&), 1355 const std::string& fmt, 1356 const std::vector<std::pair<Reg1, Reg2>>* except = nullptr) { 1357 WarnOnCombinations(reg1_registers.size() * reg2_registers.size()); 1358 1359 std::string str; 1360 for (auto reg1 : reg1_registers) { 1361 for (auto reg2 : reg2_registers) { 1362 // Check if this register pair is on the exception list. If so, skip it. 1363 if (except != nullptr) { 1364 const auto& pair = std::make_pair(reg1, reg2); 1365 if (std::find(except->begin(), except->end(), pair) != except->end()) { 1366 continue; 1367 } 1368 } 1369 1370 if (f != nullptr) { 1371 (assembler_.get()->*f)(reg1, reg2); 1372 } 1373 std::string base = fmt; 1374 1375 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 1376 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 1377 1378 str += base; 1379 str += "\n"; 1380 } 1381 } 1382 return str; 1383 } 1384 1385 template <typename Reg1, typename Reg2> RepeatTemplatedRegistersNoDupes(void (Ass::* f)(Reg1,Reg2),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),const std::string & fmt)1386 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2), 1387 ArrayRef<const Reg1> reg1_registers, 1388 ArrayRef<const Reg2> reg2_registers, 1389 std::string (AssemblerTest::*GetName1)(const Reg1&), 1390 std::string (AssemblerTest::*GetName2)(const Reg2&), 1391 const std::string& fmt) { 1392 WarnOnCombinations(reg1_registers.size() * reg2_registers.size()); 1393 1394 std::string str; 1395 for (auto reg1 : reg1_registers) { 1396 for (auto reg2 : reg2_registers) { 1397 if (reg1 == reg2) continue; 1398 if (f != nullptr) { 1399 (assembler_.get()->*f)(reg1, reg2); 1400 } 1401 std::string base = fmt; 1402 1403 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 1404 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 1405 1406 str += base; 1407 str += "\n"; 1408 } 1409 } 1410 return str; 1411 } 1412 1413 template <typename Reg1, typename Reg2, typename Reg3> RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2,Reg3),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),const std::string & fmt)1414 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3), 1415 ArrayRef<const Reg1> reg1_registers, 1416 ArrayRef<const Reg2> reg2_registers, 1417 ArrayRef<const Reg3> reg3_registers, 1418 std::string (AssemblerTest::*GetName1)(const Reg1&), 1419 std::string (AssemblerTest::*GetName2)(const Reg2&), 1420 std::string (AssemblerTest::*GetName3)(const Reg3&), 1421 const std::string& fmt) { 1422 std::string str; 1423 for (auto reg1 : reg1_registers) { 1424 for (auto reg2 : reg2_registers) { 1425 for (auto reg3 : reg3_registers) { 1426 if (f != nullptr) { 1427 (assembler_.get()->*f)(reg1, reg2, reg3); 1428 } 1429 std::string base = fmt; 1430 1431 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 1432 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 1433 ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base); 1434 1435 str += base; 1436 str += "\n"; 1437 } 1438 } 1439 } 1440 return str; 1441 } 1442 1443 template <typename Reg1, typename Reg2, typename Reg3, typename Reg4> RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2,Reg3,Reg4),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,ArrayRef<const Reg3> reg3_registers,ArrayRef<const Reg4> reg4_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),std::string (AssemblerTest::* GetName4)(const Reg4 &),const std::string & fmt)1444 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3, Reg4), 1445 ArrayRef<const Reg1> reg1_registers, 1446 ArrayRef<const Reg2> reg2_registers, 1447 ArrayRef<const Reg3> reg3_registers, 1448 ArrayRef<const Reg4> reg4_registers, 1449 std::string (AssemblerTest::*GetName1)(const Reg1&), 1450 std::string (AssemblerTest::*GetName2)(const Reg2&), 1451 std::string (AssemblerTest::*GetName3)(const Reg3&), 1452 std::string (AssemblerTest::*GetName4)(const Reg4&), 1453 const std::string& fmt) { 1454 std::string str; 1455 for (auto reg1 : reg1_registers) { 1456 for (auto reg2 : reg2_registers) { 1457 for (auto reg3 : reg3_registers) { 1458 for (auto reg4 : reg4_registers) { 1459 if (f != nullptr) { 1460 (assembler_.get()->*f)(reg1, reg2, reg3, reg4); 1461 } 1462 std::string base = fmt; 1463 1464 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 1465 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 1466 ReplaceReg(REG3_TOKEN, (this->*GetName3)(reg3), &base); 1467 ReplaceReg(REG4_TOKEN, (this->*GetName4)(reg4), &base); 1468 1469 str += base; 1470 str += "\n"; 1471 } 1472 } 1473 } 1474 } 1475 return str; 1476 } 1477 1478 template <typename Reg1, typename Reg2> RepeatTemplatedRegistersImm(void (Ass::* f)(Reg1,Reg2,const Imm &),ArrayRef<const Reg1> reg1_registers,ArrayRef<const Reg2> reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),size_t imm_bytes,const std::string & fmt)1479 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&), 1480 ArrayRef<const Reg1> reg1_registers, 1481 ArrayRef<const Reg2> reg2_registers, 1482 std::string (AssemblerTest::*GetName1)(const Reg1&), 1483 std::string (AssemblerTest::*GetName2)(const Reg2&), 1484 size_t imm_bytes, 1485 const std::string& fmt) { 1486 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes); 1487 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size()); 1488 1489 std::string str; 1490 for (auto reg1 : reg1_registers) { 1491 for (auto reg2 : reg2_registers) { 1492 for (int64_t imm : imms) { 1493 Imm new_imm = CreateImmediate(imm); 1494 if (f != nullptr) { 1495 (assembler_.get()->*f)(reg1, reg2, new_imm); 1496 } 1497 std::string base = fmt; 1498 1499 ReplaceReg(REG1_TOKEN, (this->*GetName1)(reg1), &base); 1500 ReplaceReg(REG2_TOKEN, (this->*GetName2)(reg2), &base); 1501 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base); 1502 1503 str += base; 1504 str += "\n"; 1505 } 1506 } 1507 } 1508 return str; 1509 } 1510 GetAddrName(const Addr & addr)1511 std::string GetAddrName(const Addr& addr) { 1512 std::ostringstream saddr; 1513 saddr << addr; 1514 return saddr.str(); 1515 } 1516 1517 template <RegisterView kRegView> GetRegName(const Reg & reg)1518 std::string GetRegName(const Reg& reg) { 1519 std::ostringstream sreg; 1520 switch (kRegView) { 1521 case RegisterView::kUsePrimaryName: 1522 sreg << reg; 1523 break; 1524 1525 case RegisterView::kUseSecondaryName: 1526 sreg << GetSecondaryRegisterName(reg); 1527 break; 1528 1529 case RegisterView::kUseTertiaryName: 1530 sreg << GetTertiaryRegisterName(reg); 1531 break; 1532 1533 case RegisterView::kUseQuaternaryName: 1534 sreg << GetQuaternaryRegisterName(reg); 1535 break; 1536 } 1537 return sreg.str(); 1538 } 1539 GetFPRegName(const FPReg & reg)1540 std::string GetFPRegName(const FPReg& reg) { 1541 std::ostringstream sreg; 1542 sreg << reg; 1543 return sreg.str(); 1544 } 1545 GetVecRegName(const VecReg & reg)1546 std::string GetVecRegName(const VecReg& reg) { 1547 std::ostringstream sreg; 1548 sreg << reg; 1549 return sreg.str(); 1550 } 1551 WarnOnCombinations(size_t count)1552 void WarnOnCombinations(size_t count) { 1553 if (count > kWarnManyCombinationsThreshold) { 1554 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow."; 1555 } 1556 } 1557 ReplaceReg(const std::string & reg_token,const std::string & replacement,std::string * str)1558 static void ReplaceReg(const std::string& reg_token, 1559 const std::string& replacement, 1560 /*inout*/ std::string* str) { 1561 size_t reg_index; 1562 while ((reg_index = str->find(reg_token)) != std::string::npos) { 1563 str->replace(reg_index, reg_token.length(), replacement); 1564 } 1565 } 1566 ReplaceImm(int64_t imm,int64_t bias,int64_t multiplier,std::string * str)1567 static void ReplaceImm(int64_t imm, 1568 int64_t bias, 1569 int64_t multiplier, 1570 /*inout*/ std::string* str) { 1571 size_t imm_index = str->find(IMM_TOKEN); 1572 if (imm_index != std::string::npos) { 1573 std::ostringstream sreg; 1574 sreg << imm * multiplier + bias; 1575 std::string imm_string = sreg.str(); 1576 str->replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string); 1577 } 1578 } 1579 ReplaceAddr(const std::string & replacement,std::string * str)1580 static void ReplaceAddr(const std::string& replacement, /*inout*/ std::string* str) { 1581 size_t addr_index; 1582 if ((addr_index = str->find(ADDRESS_TOKEN)) != std::string::npos) { 1583 str->replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), replacement); 1584 } 1585 } 1586 1587 static constexpr const char* ADDRESS_TOKEN = "{mem}"; 1588 static constexpr const char* REG_TOKEN = "{reg}"; 1589 static constexpr const char* REG1_TOKEN = "{reg1}"; 1590 static constexpr const char* REG2_TOKEN = "{reg2}"; 1591 static constexpr const char* REG3_TOKEN = "{reg3}"; 1592 static constexpr const char* REG4_TOKEN = "{reg4}"; 1593 static constexpr const char* IMM_TOKEN = "{imm}"; 1594 1595 private: 1596 template <RegisterView kRegView> RepeatRegisterImm(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)1597 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&), 1598 size_t imm_bytes, 1599 const std::string& fmt) { 1600 ArrayRef<const Reg> registers = GetRegisters(); 1601 std::string str; 1602 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes); 1603 1604 WarnOnCombinations(registers.size() * imms.size()); 1605 1606 for (auto reg : registers) { 1607 for (int64_t imm : imms) { 1608 Imm new_imm = CreateImmediate(imm); 1609 if (f != nullptr) { 1610 (assembler_.get()->*f)(reg, new_imm); 1611 } 1612 std::string base = fmt; 1613 1614 ReplaceReg(REG_TOKEN, GetRegName<kRegView>(reg), &base); 1615 ReplaceImm(imm, /*bias=*/ 0, /*multiplier=*/ 1, &base); 1616 1617 str += base; 1618 str += "\n"; 1619 } 1620 } 1621 return str; 1622 } 1623 1624 // Override this to pad the code with NOPs to a certain size if needed. Pad(std::vector<uint8_t> & data)1625 virtual void Pad([[maybe_unused]] std::vector<uint8_t>& data) {} 1626 DriverWrapper(const std::string & assembly_text,const std::string & test_name)1627 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) { 1628 assembler_->FinalizeCode(); 1629 size_t cs = assembler_->CodeSize(); 1630 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs)); 1631 MemoryRegion code(&(*data)[0], data->size()); 1632 assembler_->CopyInstructions(code); 1633 Pad(*data); 1634 Driver(*data, assembly_text, test_name); 1635 } 1636 1637 static constexpr size_t kWarnManyCombinationsThreshold = 500; 1638 1639 MallocArenaPool pool_; 1640 std::unique_ptr<ArenaAllocator> allocator_; 1641 std::unique_ptr<Ass> assembler_; 1642 1643 DISALLOW_COPY_AND_ASSIGN(AssemblerTest); 1644 }; 1645 1646 } // namespace art 1647 1648 #endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_ 1649