diff options
author | 2015-09-17 13:34:00 -0700 | |
---|---|---|
committer | 2015-10-05 18:12:30 -0700 | |
commit | dbce0d738e9d7956d2bd73e932a0fdd28f2229b4 (patch) | |
tree | 336a92e522c4f20386f65f2a34534f982cf28089 /compiler/utils/assembler_test.h | |
parent | 002117f95896ffa5db74bee808ae61e876b6e8b0 (diff) |
MIPS64r6 Assembler Tests
Assembler tests for:
- SQRT.fmt - ABS.fmt - ROUND.L.fmt - ROUND.W.fmt
- CEIL.L.fmt - CEIL.W.fmt - FLOOR.L.fmt - FLOOR.W.fmt
- SEL.fmt - RINT.fmt - CLASS.fmt - MIN.fmt
- MAX.fmt - cvt.d.l - BITSWAP - DBITSWAP
- DSBH - DSHD - WSBH - ROTR
- SELEQZ - SELNEZ - CLZ - CLO
- DCLZ - DCLO - SC - SCD
- LL - LLD
These are the assembler instructions which were added to support
intrinsic functions on MIPS64. Tests for additional assembler
instructions will follow.
Support added to the testing infrastructure for:
- Assembler instructions which use three registers; previously
instructions were limited to one, or two, registers.
- Immediate values which have their sizes specified by the number of
bits required to store them rather than the number of bytes, in both
signed and unsigned versions.
Change-Id: I38c07dcbf2539825b25bed13aac05a26fa594b0b
Diffstat (limited to 'compiler/utils/assembler_test.h')
-rw-r--r-- | compiler/utils/assembler_test.h | 202 |
1 files changed, 195 insertions, 7 deletions
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h index 017402dbd3..bd994f46fc 100644 --- a/compiler/utils/assembler_test.h +++ b/compiler/utils/assembler_test.h @@ -92,6 +92,17 @@ class AssemblerTest : public testing::Test { fmt); } + std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), std::string fmt) { + return RepeatTemplatedRegisters<Reg, Reg, Reg>(f, + GetRegisters(), + GetRegisters(), + GetRegisters(), + &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, + &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, + &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>, + fmt); + } + std::string Repeatrb(void (Ass::*f)(Reg, Reg), std::string fmt) { return RepeatTemplatedRegisters<Reg, Reg>(f, GetRegisters(), @@ -118,6 +129,66 @@ class AssemblerTest : public testing::Test { return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt); } + template <typename Reg1Type, typename Reg2Type, typename ImmType, + RegisterView Reg1View, RegisterView Reg2View> + std::string RepeatRegRegImmBits(void (Ass::*f)(Reg1Type, Reg2Type, ImmType), + int imm_bits, + std::string fmt) { + const std::vector<Reg1Type*> reg1_registers = GetRegisters(); + const std::vector<Reg2Type*> reg2_registers = GetRegisters(); + std::string str; + std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), imm_bits > 0); + + for (auto reg1 : reg1_registers) { + for (auto reg2 : reg2_registers) { + for (int64_t imm : imms) { + ImmType new_imm = CreateImmediate(imm); + (assembler_.get()->*f)(*reg1, *reg2, new_imm); + std::string base = fmt; + + std::string reg1_string = GetRegName<Reg1View>(*reg1); + size_t reg1_index; + while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) { + base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string); + } + + std::string reg2_string = GetRegName<Reg2View>(*reg2); + size_t reg2_index; + while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) { + base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string); + } + + size_t imm_index = base.find(IMM_TOKEN); + if (imm_index != std::string::npos) { + std::ostringstream sreg; + sreg << imm; + std::string imm_string = sreg.str(); + base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string); + } + + if (str.size() > 0) { + str += "\n"; + } + str += base; + } + } + } + // Add a newline at the end. + str += "\n"; + return str; + } + + template <typename Reg1Type, typename Reg2Type, typename ImmType> + std::string RepeatRRIb(void (Ass::*f)(Reg1Type, Reg2Type, ImmType), + int imm_bits, + std::string fmt) { + return RepeatRegRegImmBits<Reg1Type, + Reg2Type, + ImmType, + RegisterView::kUsePrimaryName, + RegisterView::kUsePrimaryName>(f, imm_bits, fmt); + } + std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), std::string fmt) { return RepeatTemplatedRegisters<FPReg, FPReg>(f, GetFPRegisters(), @@ -127,14 +198,27 @@ class AssemblerTest : public testing::Test { fmt); } - std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&), size_t imm_bytes, std::string fmt) { + std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), std::string fmt) { + return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f, + GetFPRegisters(), + GetFPRegisters(), + GetFPRegisters(), + &AssemblerTest::GetFPRegName, + &AssemblerTest::GetFPRegName, + &AssemblerTest::GetFPRegName, + fmt); + } + + std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&), + size_t imm_bytes, + std::string fmt) { return RepeatTemplatedRegistersImm<FPReg, FPReg>(f, - GetFPRegisters(), - GetFPRegisters(), - &AssemblerTest::GetFPRegName, - &AssemblerTest::GetFPRegName, - imm_bytes, - fmt); + GetFPRegisters(), + GetFPRegisters(), + &AssemblerTest::GetFPRegName, + &AssemblerTest::GetFPRegName, + imm_bytes, + fmt); } std::string RepeatFR(void (Ass::*f)(FPReg, Reg), std::string fmt) { @@ -339,6 +423,63 @@ class AssemblerTest : public testing::Test { return res; } + const int kMaxBitsExhaustiveTest = 8; + + // Create a couple of immediate values up to the number of bits given. + virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) { + CHECK_GT(imm_bits, 0); + CHECK_LE(imm_bits, 64); + std::vector<int64_t> res; + + if (imm_bits <= kMaxBitsExhaustiveTest) { + if (as_uint) { + for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) { + res.push_back(static_cast<int64_t>(i)); + } + } else { + for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) { + res.push_back(i); + } + } + } else { + if (as_uint) { + for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest); + i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest); + i++) { + res.push_back(static_cast<int64_t>(i)); + } + for (int i = 0; i <= imm_bits; i++) { + uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) + + ((MaxInt<uint64_t>(imm_bits) - + (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1)) + * i / imm_bits); + res.push_back(static_cast<int64_t>(j)); + } + } else { + for (int i = 0; i <= imm_bits; i++) { + int64_t j = MinInt<int64_t>(imm_bits) + + ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) - + MinInt<int64_t>(imm_bits)) + * i) / imm_bits); + res.push_back(static_cast<int64_t>(j)); + } + for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest); + i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest); + i++) { + res.push_back(static_cast<int64_t>(i)); + } + for (int i = 0; i <= imm_bits; i++) { + int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) + + ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1)) + * i / imm_bits); + res.push_back(static_cast<int64_t>(j)); + } + } + } + + return res; + } + // Create an immediate from the specific value. virtual Imm CreateImmediate(int64_t imm_value) = 0; @@ -406,6 +547,52 @@ class AssemblerTest : public testing::Test { return str; } + template <typename Reg1, typename Reg2, typename Reg3> + std::string 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&), + std::string fmt) { + std::string str; + for (auto reg1 : reg1_registers) { + for (auto reg2 : reg2_registers) { + for (auto reg3 : reg3_registers) { + (assembler_.get()->*f)(*reg1, *reg2, *reg3); + std::string base = fmt; + + std::string reg1_string = (this->*GetName1)(*reg1); + size_t reg1_index; + while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) { + base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string); + } + + std::string reg2_string = (this->*GetName2)(*reg2); + size_t reg2_index; + while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) { + base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string); + } + + std::string reg3_string = (this->*GetName3)(*reg3); + size_t reg3_index; + while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) { + base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string); + } + + if (str.size() > 0) { + str += "\n"; + } + str += base; + } + } + } + // Add a newline at the end. + str += "\n"; + return str; + } + template <typename Reg1, typename Reg2> std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&), const std::vector<Reg1*> reg1_registers, @@ -500,6 +687,7 @@ class AssemblerTest : public testing::Test { static constexpr const char* REG_TOKEN = "{reg}"; static constexpr const char* REG1_TOKEN = "{reg1}"; static constexpr const char* REG2_TOKEN = "{reg2}"; + static constexpr const char* REG3_TOKEN = "{reg3}"; static constexpr const char* IMM_TOKEN = "{imm}"; private: |