From dbce0d738e9d7956d2bd73e932a0fdd28f2229b4 Mon Sep 17 00:00:00 2001 From: Chris Larsen Date: Thu, 17 Sep 2015 13:34:00 -0700 Subject: 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 --- compiler/utils/assembler_test.h | 202 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 195 insertions(+), 7 deletions(-) (limited to 'compiler/utils/assembler_test.h') 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(f, + GetRegisters(), + GetRegisters(), + GetRegisters(), + &AssemblerTest::GetRegName, + &AssemblerTest::GetRegName, + &AssemblerTest::GetRegName, + fmt); + } + std::string Repeatrb(void (Ass::*f)(Reg, Reg), std::string fmt) { return RepeatTemplatedRegisters(f, GetRegisters(), @@ -118,6 +129,66 @@ class AssemblerTest : public testing::Test { return RepeatRegisterImm(f, imm_bytes, fmt); } + template + std::string RepeatRegRegImmBits(void (Ass::*f)(Reg1Type, Reg2Type, ImmType), + int imm_bits, + std::string fmt) { + const std::vector reg1_registers = GetRegisters(); + const std::vector reg2_registers = GetRegisters(); + std::string str; + std::vector 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(*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(*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 + std::string RepeatRRIb(void (Ass::*f)(Reg1Type, Reg2Type, ImmType), + int imm_bits, + std::string fmt) { + return RepeatRegRegImmBits(f, imm_bits, fmt); + } + std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), std::string fmt) { return RepeatTemplatedRegisters(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(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(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 CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) { + CHECK_GT(imm_bits, 0); + CHECK_LE(imm_bits, 64); + std::vector res; + + if (imm_bits <= kMaxBitsExhaustiveTest) { + if (as_uint) { + for (uint64_t i = MinInt(imm_bits); i <= MaxInt(imm_bits); i++) { + res.push_back(static_cast(i)); + } + } else { + for (int64_t i = MinInt(imm_bits); i <= MaxInt(imm_bits); i++) { + res.push_back(i); + } + } + } else { + if (as_uint) { + for (uint64_t i = MinInt(kMaxBitsExhaustiveTest); + i <= MaxInt(kMaxBitsExhaustiveTest); + i++) { + res.push_back(static_cast(i)); + } + for (int i = 0; i <= imm_bits; i++) { + uint64_t j = (MaxInt(kMaxBitsExhaustiveTest) + 1) + + ((MaxInt(imm_bits) - + (MaxInt(kMaxBitsExhaustiveTest) + 1)) + * i / imm_bits); + res.push_back(static_cast(j)); + } + } else { + for (int i = 0; i <= imm_bits; i++) { + int64_t j = MinInt(imm_bits) + + ((((MinInt(kMaxBitsExhaustiveTest) - 1) - + MinInt(imm_bits)) + * i) / imm_bits); + res.push_back(static_cast(j)); + } + for (int64_t i = MinInt(kMaxBitsExhaustiveTest); + i <= MaxInt(kMaxBitsExhaustiveTest); + i++) { + res.push_back(static_cast(i)); + } + for (int i = 0; i <= imm_bits; i++) { + int64_t j = (MaxInt(kMaxBitsExhaustiveTest) + 1) + + ((MaxInt(imm_bits) - (MaxInt(kMaxBitsExhaustiveTest) + 1)) + * i / imm_bits); + res.push_back(static_cast(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 + std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3), + const std::vector reg1_registers, + const std::vector reg2_registers, + const std::vector 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 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&), const std::vector 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: -- cgit v1.2.3-59-g8ed1b