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