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