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