diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 8fbfa74a2b..e0106f97f8 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -1798,6 +1798,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_AT: return aliasNYI(); case ARM64_INS_BFI: + // TODO no tests of alias if (opcode == Opcode::AArch64_BFMWri) { // bfi wd, wn, #lsb, #width; alias for // bfm wd, wn, #(-lsb MOD 32), #(width - 1) @@ -1814,6 +1815,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_BFXIL: + // TODO no tests for alias if (opcode == Opcode::AArch64_BFMWri || opcode == Opcode::AArch64_BFMXri) { // bfxil rd, rn, #lsb, #width; alias for @@ -1896,6 +1898,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_CSET: + // TODO no usage in regression tests if (opcode == Opcode::AArch64_CSINCWr || opcode == Opcode::AArch64_CSINCXr) { // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) @@ -1952,6 +1955,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_IC: return aliasNYI(); case ARM64_INS_LSL: + // TODO no usage in regression tests if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { // lsl rd, rn, #shift; alias for: @@ -1998,6 +2002,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MNEG: + // TODO no test if (opcode == Opcode::AArch64_MSUBXrrr) { // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr operandCount = 4; @@ -2016,6 +2021,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MOV: + // TODO no specific tests if (opcode == Opcode::AArch64_AND_PPzPP) { // mov pd.b, pg/z, pn.b; alias for: and pd.b, pg/z, pn.b, pn.b operandCount = 4; @@ -2272,6 +2278,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MUL: + // TODO add comment if (opcode == Opcode::AArch64_MADDXrrr || opcode == Opcode::AArch64_MADDWrrr) { operandCount = 4; @@ -2310,6 +2317,7 @@ void InstructionMetadata::revertAliasing() { } if (opcode == Opcode::AArch64_NOTv16i8 || opcode == Opcode::AArch64_NOTv8i8) { + // TODO needs tests // mvn vd.t, vn.t; alias for : not vd.t, vn.t // Blank entry was for a legitimate alias, however operands were // identical so nothing to alter between the instructions. @@ -2317,6 +2325,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_NEG: + // TODO needs tests if (opcode == Opcode::AArch64_SUBWrs || opcode == Opcode::AArch64_SUBXrs) { // neg rd, rm{, shift #amount}; alias for: @@ -2364,7 +2373,7 @@ void InstructionMetadata::revertAliasing() { return aliasNYI(); case ARM64_INS_NOT: if (opcode == Opcode::AArch64_EOR_PPzPP) { - // not pd.b, pg/z, pn.b; alisas for: eor pd.b, pg/z, pn.b, pg.b + // not pd.b, pg/z, pn.b; alias for: eor pd.b, pg/z, pn.b, pg.b operandCount = 4; operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; @@ -2388,6 +2397,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_ROR: + // TODO needs test if (opcode == Opcode::AArch64_RORVWr || opcode == Opcode::AArch64_RORVXr) { // ror wd, wn, wm; alias for : rorv wd, wn, wm @@ -2398,6 +2408,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SBFIZ: + // TODO needs test if (opcode == Opcode::AArch64_SBFMWri || opcode == Opcode::AArch64_SBFMXri) { operands[3].imm -= 1; @@ -2412,6 +2423,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SBFX: + // TODO needs test if (opcode == Opcode::AArch64_SBFMWri || opcode == Opcode::AArch64_SBFMXri) { // sbfx rd, rn, #lsb, #width; alias for @@ -2482,6 +2494,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SYS: { + // TODO no test // Extract IC/DC/AT/TLBI operation if (std::string(mnemonic) == "dc") { if (operandStr.substr(0, 3) == "zva") { @@ -2502,6 +2515,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_TLBI: return aliasNYI(); case ARM64_INS_TST: + // TODO needs test for register case if (opcode == Opcode::AArch64_ANDSWrs || opcode == Opcode::AArch64_ANDSXrs || opcode == Opcode::AArch64_ANDSWri || @@ -2525,6 +2539,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UBFIZ: + // TODO needs test and comment if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { operands[3].imm -= 1; @@ -2539,6 +2554,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UBFX: + // TODO needs test if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { // ubfx rd, rn, #lsb, #width; alias for @@ -2560,6 +2576,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UXTB: + // TODO needs test // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 if (opcode == Opcode::AArch64_UBFMWri) { operandCount = 4; diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 237b0518a3..216a2c9297 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,10 +21,8 @@ void RegressionTest::TearDown() { } } -void RegressionTest::run(const char* source, const char* triple, - const char* extensions) { - testing::internal::CaptureStdout(); - +void RegressionTest::createArchitecture(const char* source, const char* triple, + const char* extensions) { // Zero-out process memory from any prior runs if (processMemory_ != nullptr) std::memset(processMemory_, '\0', processMemorySize_); @@ -47,56 +45,44 @@ void RegressionTest::run(const char* source, const char* triple, // The process image is finalised by the createStack method // which creates and populates the initial process stack. // The created process image can be accessed via a shared_ptr - // returned by the getProcessImage method. + // returned by the getProcessImage method process_ = std::make_unique( simeng::span(reinterpret_cast(code_), codeSize_)); ASSERT_TRUE(process_->isValid()); - uint64_t entryPoint = process_->getEntryPoint(); + entryPoint_ = process_->getEntryPoint(); processMemorySize_ = process_->getProcessImageSize(); + // This instance of procImgPtr pointer needs to be shared because // getMemoryValue in RegressionTest.hh uses reference to the class - // member processMemory_. + // member processMemory_ std::shared_ptr procImgPtr = process_->getProcessImage(); processMemory_ = procImgPtr.get(); - // Create memory interfaces for instruction and data access. - // For each memory interface, a dereferenced shared_ptr to the - // processImage is passed as argument. - simeng::memory::FlatMemoryInterface instructionMemory(processMemory_, - processMemorySize_); - - std::unique_ptr flatDataMemory = - std::make_unique(processMemory_, - processMemorySize_); + // Populate the heap with initial data (specified by the test being run) + ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), + process_->getInitialStackPointer()); + std::copy(initialHeapData_.begin(), initialHeapData_.end(), + processMemory_ + process_->getHeapStart()); - std::unique_ptr - fixedLatencyDataMemory = - std::make_unique( - processMemory_, processMemorySize_, 4); - std::unique_ptr dataMemory; + ASSERT_TRUE(process_ != nullptr); // Create the OS kernel and the process - simeng::kernel::Linux kernel( + kernel_ = std::make_unique( simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] .as()); - kernel.createProcess(*process_); - - // Populate the heap with initial data (specified by the test being run). - ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), - process_->getInitialStackPointer()); - std::copy(initialHeapData_.begin(), initialHeapData_.end(), - processMemory_ + process_->getHeapStart()); + kernel_->createProcess(*process_); // Create the architecture - architecture_ = createArchitecture(kernel); + architecture_ = instantiateArchitecture(*kernel_); +} - // Create a port allocator for an out-of-order core - std::unique_ptr portAllocator = - createPortAllocator(); +void RegressionTest::createCore(const char* source, const char* triple, + const char* extensions) { + // Create the architecture, kernel and process + createArchitecture(source, triple, extensions); // Create a branch predictor for a pipelined core - std::unique_ptr predictor_ = nullptr; std::string predictorType = simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] .as(); @@ -106,34 +92,61 @@ void RegressionTest::run(const char* source, const char* triple, predictor_ = std::make_unique(); } + // Create memory interfaces for instruction and data access. + // For each memory interface, a dereferenced shared_ptr to the + // processImage is passed as an argument + + ASSERT_TRUE(processMemory_ != nullptr); + + instructionMemory_ = std::make_unique( + processMemory_, processMemorySize_); + + flatDataMemory_ = std::make_unique( + processMemory_, processMemorySize_); + + fixedLatencyDataMemory_ = + std::make_unique( + processMemory_, processMemorySize_, 4); + // Create the core model switch (std::get<0>(GetParam())) { case EMULATION: core_ = std::make_unique( - instructionMemory, *flatDataMemory, entryPoint, processMemorySize_, - *architecture_); - dataMemory = std::move(flatDataMemory); + *instructionMemory_, *flatDataMemory_, entryPoint_, + processMemorySize_, *architecture_); + dataMemory_ = std::move(flatDataMemory_); break; case INORDER: core_ = std::make_unique( - instructionMemory, *flatDataMemory, processMemorySize_, entryPoint, - *architecture_, *predictor_); - dataMemory = std::move(flatDataMemory); + *instructionMemory_, *flatDataMemory_, processMemorySize_, + entryPoint_, *architecture_, *predictor_); + dataMemory_ = std::move(flatDataMemory_); break; case OUTOFORDER: + // Create a port allocator for an out-of-order core + portAllocator_ = createPortAllocator(); + core_ = std::make_unique( - instructionMemory, *fixedLatencyDataMemory, processMemorySize_, - entryPoint, *architecture_, *predictor_, *portAllocator); - dataMemory = std::move(fixedLatencyDataMemory); + *instructionMemory_, *fixedLatencyDataMemory_, processMemorySize_, + entryPoint_, *architecture_, *predictor_, *portAllocator_); + dataMemory_ = std::move(fixedLatencyDataMemory_); break; } +} + +void RegressionTest::run(const char* source, const char* triple, + const char* extensions) { + testing::internal::CaptureStdout(); + + // Create the core, memory interfaces, kernel and process + createCore(source, triple, extensions); // Run the core model until the program is complete - while (!core_->hasHalted() || dataMemory->hasPendingRequests()) { + while (!core_->hasHalted() || dataMemory_->hasPendingRequests()) { ASSERT_LT(numTicks_, maxTicks_) << "Maximum tick count exceeded."; core_->tick(); - instructionMemory.tick(); - dataMemory->tick(); + instructionMemory_->tick(); + dataMemory_->tick(); numTicks_++; } @@ -143,6 +156,24 @@ void RegressionTest::run(const char* source, const char* triple, programFinished_ = true; } +void RegressionTest::checkGroup(const char* source, const char* triple, + const char* extensions, + const std::vector& expectedGroups) { + createArchitecture(source, triple, extensions); + + std::vector> macroOp; + architecture_->predecode(code_, 4, 0, macroOp); + + // Check that there is one expectation group per micro-op + EXPECT_EQ(macroOp.size(), expectedGroups.size()); + + // Check the assigned and expected group for each micro-op match + for (size_t i = 0; i < macroOp.size(); i++) { + auto group = macroOp[i]->getGroup(); + EXPECT_EQ(group, expectedGroups[i]); + } +} + void RegressionTest::assemble(const char* source, const char* triple, const char* extensions) { // Get LLVM target diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 86c3252c29..a110ff80d1 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -71,12 +71,8 @@ class RegressionTest /** Generate a default YAML-formatted configuration. */ virtual void generateConfig() const = 0; - /** Run the assembly in `source`, building it for the target `triple` and ISA - * extensions. */ - void run(const char* source, const char* triple, const char* extensions); - - /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + /** Instantiate an ISA specific architecture from a kernel. */ + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const = 0; /** Create a port allocator for an out-of-order core model. */ @@ -84,6 +80,21 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; + /** Create the kernel then instantiate an ISA specific architecture. Populates + * the architecture_ member variable. */ + void createArchitecture(const char* source, const char* triple, + const char* extensions); + + /** Run the assembly in `source`, building it for the target `triple` and ISA + * extensions. */ + void run(const char* source, const char* triple, const char* extensions); + + /** Predecode the first instruction in source and check the assigned group + * matches the expectation. */ + void checkGroup(const char* source, const char* triple, + const char* extensions, + const std::vector& expectedGroups); + /** Get the value of an architectural register. */ template T getRegister(simeng::Register reg) const { @@ -108,41 +119,69 @@ class RegressionTest /** The initial data to populate the heap with. */ std::vector initialHeapData_; - /** The maximum number of ticks to run before aborting the test. */ - uint64_t maxTicks_ = UINT64_MAX; - - /** The number of ticks that were run before the test program completed. */ - uint64_t numTicks_ = 0; - - /** The architecture instance. */ - std::unique_ptr architecture_; + /** The process to be executed. */ + std::unique_ptr process_; /** The process memory. */ char* processMemory_ = nullptr; - /** The size of the process memory in bytes. */ - size_t processMemorySize_ = 0; + /** The output written to stdout during the test. */ + std::string stdout_; - /** The process that was executed. */ - std::unique_ptr process_; + /** The flat binary produced by assembling the test source. */ + uint8_t* code_ = nullptr; - /** The core that was used. */ - std::unique_ptr core_ = nullptr; + /** The number of ticks that were run before the test program completed. */ + uint64_t numTicks_ = 0; - /** The output written to stdout during the test. */ - std::string stdout_; + /** The maximum number of ticks to run before aborting the test. */ + uint64_t maxTicks_ = UINT64_MAX; - /** True if the test program finished running. */ - bool programFinished_ = false; + /** Pointer to be instantiated for the architecture. */ + std::unique_ptr architecture_ = nullptr; private: /** Assemble test source to a flat binary for the given triple and ISA * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); - /** The flat binary produced by assembling the test source. */ - uint8_t* code_ = nullptr; + /** Instantiate the core according to the config. */ + void createCore(const char* source, const char* triple, + const char* extensions); + + /* Pointer to be instantiated for the kernel. */ + std::unique_ptr kernel_ = nullptr; + + /* Pointer to be instantiated for the port allocator. */ + std::unique_ptr portAllocator_ = nullptr; + + /* Pointer to be instantiated for the branch predictor. */ + std::unique_ptr predictor_ = nullptr; + + /** All possible data memory interfaces. dataMemory_ set to one of these + * depending on core type. */ + std::unique_ptr flatDataMemory_ = nullptr; + std::unique_ptr fixedLatencyDataMemory_ = + nullptr; + + /** Pointer to be instantiated for the data memory interface. */ + std::unique_ptr dataMemory_ = nullptr; + + /** Pointer to be instantiated for the instruction memory interface. */ + std::unique_ptr instructionMemory_ = nullptr; + + /** Pointer to be instantiated for the core. */ + std::unique_ptr core_ = nullptr; + + /** The size of the process memory in bytes. */ + size_t processMemorySize_ = 0; + + /** True if the test program finished running. */ + bool programFinished_ = false; /** The size of the assembled flat binary in bytes. */ size_t codeSize_ = 0; + + /** The entry point of the process. */ + uint64_t entryPoint_ = 0; }; diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index ffe9f60fd3..90a1386c23 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -6,19 +6,19 @@ using namespace simeng::arch::aarch64; void AArch64RegressionTest::run(const char* source) { - // Initialise LLVM - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAArch64AsmParser(); - - const char* subtargetFeatures; -#if SIMENG_LLVM_VERSION < 14 - subtargetFeatures = "+sve,+lse"; -#else - subtargetFeatures = "+sve,+lse,+sve2,+sme,+sme-f64"; -#endif - - RegressionTest::run(source, "aarch64", subtargetFeatures); + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(); + + RegressionTest::run(source, "aarch64", subtargetFeatures.c_str()); +} + +void AArch64RegressionTest::checkGroup( + const char* source, const std::vector& expectedGroups) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(); + + RegressionTest::checkGroup(source, "aarch64", subtargetFeatures.c_str(), + expectedGroups); } void AArch64RegressionTest::generateConfig() const { @@ -47,7 +47,8 @@ void AArch64RegressionTest::generateConfig() const { } std::unique_ptr -AArch64RegressionTest::createArchitecture(simeng::kernel::Linux& kernel) const { +AArch64RegressionTest::instantiateArchitecture( + simeng::kernel::Linux& kernel) const { return std::make_unique(kernel); } diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 70507408b8..b0774c15c6 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -189,6 +189,21 @@ inline std::vector> genCoreTypeSVLPairs( checkMatrixRegisterCol(tag, index, __VA_ARGS__); \ } +/** A helper macro to predecode the first instruction in a snippet of Armv9.2-a + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. + */ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}); \ + } \ + if (HasFatalFailure()) return + /** The test fixture for all AArch64 regression tests. */ class AArch64RegressionTest : public RegressionTest { protected: @@ -197,11 +212,16 @@ class AArch64RegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source); + /** Run the first instruction in source through predecode and check the + * groups. */ + void checkGroup(const char* source, + const std::vector& expectedGroups); + /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; - /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + /** Instantiate an ISA specific architecture from a kernel. */ + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; /** Create a port allocator for an out-of-order core model. */ @@ -209,6 +229,22 @@ class AArch64RegressionTest : public RegressionTest { ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const override; + /** Initialise LLVM */ + void initialiseLLVM() { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64AsmParser(); + } + + /** Get the subtarget feature string based on LLVM version being used */ + std::string getSubtargetFeaturesString() { +#if SIMENG_LLVM_VERSION < 14 + return "+sve,+lse"; +#else + return "+sve,+lse,+sve2,+sme,+sme-f64"; +#endif + } + /** Check the elements of a Neon register. * * This should be invoked via the `CHECK_NEON` macro in order to provide diff --git a/test/regression/aarch64/MicroOperation.cc b/test/regression/aarch64/MicroOperation.cc index 2cd14b1d10..ceca4744e0 100644 --- a/test/regression/aarch64/MicroOperation.cc +++ b/test/regression/aarch64/MicroOperation.cc @@ -10,6 +10,7 @@ namespace { using MicroOp = AArch64RegressionTest; +using namespace simeng::arch::aarch64; TEST_P(MicroOp, ld1Two) { initialHeapData_.resize(32); @@ -292,6 +293,10 @@ TEST_P(MicroOp, loadPairD) { CHECK_NEON(6, double, {-3.0}); CHECK_NEON(7, double, {1.0}); CHECK_NEON(8, double, {-1.0}); + + EXPECT_GROUP(R"(ldp d1, d2, [x0], #16)", InstructionGroups::LOAD_SCALAR, + InstructionGroups::LOAD_SCALAR, + InstructionGroups::INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(MicroOp, loadPairQ) { diff --git a/test/regression/aarch64/SmokeTest.cc b/test/regression/aarch64/SmokeTest.cc index a3a04d6164..da214bfae8 100644 --- a/test/regression/aarch64/SmokeTest.cc +++ b/test/regression/aarch64/SmokeTest.cc @@ -3,6 +3,7 @@ namespace { using SmokeTest = AArch64RegressionTest; +using namespace simeng::arch::aarch64; // Test that a trivial instruction will execute TEST_P(SmokeTest, instruction) { @@ -10,6 +11,8 @@ TEST_P(SmokeTest, instruction) { orr x0, xzr, #7 )"); EXPECT_EQ(getGeneralRegister(0), 7u); + EXPECT_GROUP(R"(orr x0, xzr, #7)", + InstructionGroups::INT_SIMPLE_LOGICAL_NOSHIFT); } // Test a loop executing 1024 times, adding 3 to w1 each time diff --git a/test/regression/aarch64/instructions/arithmetic.cc b/test/regression/aarch64/instructions/arithmetic.cc index 7127e827f5..0d2552f355 100644 --- a/test/regression/aarch64/instructions/arithmetic.cc +++ b/test/regression/aarch64/instructions/arithmetic.cc @@ -3,6 +3,7 @@ namespace { using InstArithmetic = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstArithmetic, add) { RUN_AARCH64(R"( @@ -353,6 +354,9 @@ TEST_P(InstArithmetic, negsw) { )"); EXPECT_EQ(getNZCV(), 0b1001); EXPECT_EQ(getGeneralRegister(0), static_cast(1ul << 31)); + + EXPECT_GROUP(R"(negs w0, w1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(negs w0, w1, lsl 31)", INT_SIMPLE_ARTH); } // Test that NZCV flags are set correctly by 64-bit negs @@ -402,6 +406,9 @@ TEST_P(InstArithmetic, negsx) { )"); EXPECT_EQ(getNZCV(), 0b1001); EXPECT_EQ(getGeneralRegister(0), static_cast(1ul << 63)); + + EXPECT_GROUP(R"(negs x0, x1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(negs x0, x1, lsl 31)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, sbc) { diff --git a/test/regression/aarch64/instructions/bitmanip.cc b/test/regression/aarch64/instructions/bitmanip.cc index 69e9943f5c..a72dcb64dc 100644 --- a/test/regression/aarch64/instructions/bitmanip.cc +++ b/test/regression/aarch64/instructions/bitmanip.cc @@ -3,6 +3,7 @@ namespace { using InstBitmanip = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstBitmanip, bfm) { // 32-bit @@ -243,6 +244,17 @@ TEST_P(InstBitmanip, sbfm) { EXPECT_EQ(getGeneralRegister(7), 0x78); EXPECT_EQ(getGeneralRegister(8), 0x5678); EXPECT_EQ(getGeneralRegister(9), 0x12345678); + + EXPECT_GROUP(R"(sbfm w4, w0, #30, #27)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sbfm x6, x0, #32, #22)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxtb w7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sxtb x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxth w7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sxth x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxtw x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstBitmanip, ubfm) { diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 1acabddfeb..9c56501ae4 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -3,6 +3,16 @@ namespace { using InstComparison = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; + +// Similar to RISC-V atomic instructions, read-modify-write operations i.e. a +// load, comparison and store, is given the group LOAD_INT only. The instruction +// object is tagged with the appropriate identifiers (isLoad and isStore) but +// the group only reflects the first stage of execution. This ensures the +// instruction goes to the correct part of the pipeline i.e. the LSQ. But we +// currently do not model the rest of the atomic behaviour precisely as the +// comparison happens here also. The change of the instructions behaviour over +// its lifetime is currently not reflected in the group it is given. // Test correct Value stored after comparison for CASAL (32 & 64 bit) TEST_P(InstComparison, casal) { @@ -38,6 +48,8 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 100); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 89); + EXPECT_GROUP("casal w1, w2, [x0]", LOAD_INT); + // 64-bit initialHeapData_.resize(16); uint64_t* heap64 = reinterpret_cast(initialHeapData_.data()); @@ -69,6 +81,8 @@ TEST_P(InstComparison, casal) { 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 101); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 76); + + EXPECT_GROUP("casal x1, x7, [sp]", LOAD_INT); } // Test that NZCV flags are set correctly by the 32-bit cmn instruction @@ -94,6 +108,8 @@ TEST_P(InstComparison, cmnw) { cmn w0, #0x1 )"); EXPECT_EQ(getNZCV(), 0b0110); + + EXPECT_GROUP(R"(cmn w0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by the 64-bit cmn instruction @@ -119,6 +135,8 @@ TEST_P(InstComparison, cmnx) { cmn x0, #0x1 )"); EXPECT_EQ(getNZCV(), 0b0110); + + EXPECT_GROUP(R"(cmn X0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by the 32-bit ccmn instruction @@ -190,6 +208,9 @@ TEST_P(InstComparison, tstw) { tst w0, #0x80000000 )"); EXPECT_EQ(getNZCV(), 0b1000); + + EXPECT_GROUP(R"(tst w0, w2)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(tst w0, #0x80000000)", INT_SIMPLE_LOGICAL_NOSHIFT); } // Test that NZCV flags are set correctly by 32-bit cmp @@ -243,6 +264,8 @@ TEST_P(InstComparison, cmpw) { cmp w1, #1 )"); EXPECT_EQ(getNZCV(), 0b0011); + + EXPECT_GROUP(R"(cmp w1, #1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by 64-bit cmp @@ -323,6 +346,8 @@ TEST_P(InstComparison, cmpx) { cmp x0, x2, uxtx 4 )"); EXPECT_EQ(getNZCV(), 0b0010); + + EXPECT_GROUP(R"(cmp x0, x2, uxtx 4)", INT_SIMPLE_ARTH); } // Test that NZCV flags are set correctly by 64-bit tst @@ -347,6 +372,9 @@ TEST_P(InstComparison, tstx) { tst x0, #0x8000000000000000 )"); EXPECT_EQ(getNZCV(), 0b1000); + + EXPECT_GROUP(R"(tst x0, x2)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(tst x0, #0b0010)", INT_SIMPLE_LOGICAL_NOSHIFT); } INSTANTIATE_TEST_SUITE_P(AArch64, InstComparison, diff --git a/test/regression/aarch64/instructions/conditional.cc b/test/regression/aarch64/instructions/conditional.cc index 88022046eb..e10d8b297d 100644 --- a/test/regression/aarch64/instructions/conditional.cc +++ b/test/regression/aarch64/instructions/conditional.cc @@ -3,6 +3,7 @@ namespace { using InstConditional = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstConditional, ccmn) { // 64-bit @@ -120,6 +121,9 @@ TEST_P(InstConditional, csetm) { EXPECT_EQ(getGeneralRegister(4), 0); EXPECT_EQ(getGeneralRegister(5), 0); EXPECT_EQ(getGeneralRegister(6), -1); + + EXPECT_GROUP(R"(csetm w6, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(csetm x6, le)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, csinc) { @@ -166,6 +170,11 @@ TEST_P(InstConditional, csinc) { EXPECT_EQ(getGeneralRegister(6), 42u); EXPECT_EQ(getGeneralRegister(7), 42u); EXPECT_EQ(getGeneralRegister(8), 43u); + + EXPECT_GROUP(R"(csinc w6, w1, w2, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cinc w8, w1, ge)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(csinc x6, x1, x2, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cinc x8, x1, ge)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, csneg) { @@ -212,6 +221,9 @@ TEST_P(InstConditional, csneg) { EXPECT_EQ(getGeneralRegister(6), 42); EXPECT_EQ(getGeneralRegister(7), 42); EXPECT_EQ(getGeneralRegister(8), -42); + + EXPECT_GROUP(R"(cneg w8, w1, ge)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cneg x8, x1, ge)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, tbz) { diff --git a/test/regression/aarch64/instructions/logical.cc b/test/regression/aarch64/instructions/logical.cc index 4ecc167a52..b21ca37bb7 100644 --- a/test/regression/aarch64/instructions/logical.cc +++ b/test/regression/aarch64/instructions/logical.cc @@ -3,6 +3,7 @@ namespace { using InstLogical = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstLogical, andw) { // 0 & 0 = 0 @@ -188,6 +189,10 @@ TEST_P(InstLogical, asrw) { asr w0, w0, w1 )"); EXPECT_EQ(getGeneralRegister(0), -8); + + // TODO being noshift seems incorrect - but potentially aliasing to SBF + EXPECT_GROUP(R"(asr w0, w0, wzr)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(asr w0, w0, #1)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, asrx) { @@ -221,6 +226,10 @@ TEST_P(InstLogical, asrx) { asr x0, x0, x1 )"); EXPECT_EQ(getGeneralRegister(0), -8); + + // TODO noshift seems incorrect - but potentially aliasing to SBF + EXPECT_GROUP(R"(asr x0, x0, xzr)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(asr x0, x0, #2)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, bic) { @@ -405,13 +414,18 @@ TEST_P(InstLogical, lsrv) { lsrv x3, x0, xzr lsrv x4, x0, x1 lsrv x5, x0, x2 - # Check lsr alias as xell + # Check lsr alias as well lsr x6, x1, x0 )"); EXPECT_EQ(getGeneralRegister(3), 7ull); EXPECT_EQ(getGeneralRegister(4), 7ull >> 31); EXPECT_EQ(getGeneralRegister(5), 7ull >> 6); EXPECT_EQ(getGeneralRegister(6), 31ull >> 7); + + EXPECT_GROUP(R"(lsr w6, w1, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr x6, x1, x0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr w6, w1, #1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr x6, x1, #1)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, orn) { @@ -475,6 +489,11 @@ TEST_P(InstLogical, orn) { EXPECT_EQ(getGeneralRegister(6), UINT64_C(-1) & ~UINT64_C(0b0101)); EXPECT_EQ(getGeneralRegister(7), UINT64_C(-1) & ~(UINT64_C(0b0101) << 60)); + + EXPECT_GROUP(R"(mvn w6, w0)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(mvn w7, w0, lsl #28)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(mvn x6, x1)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(mvn x7, x1, lsl #60)", INT_SIMPLE_LOGICAL); } TEST_P(InstLogical, rorv) { diff --git a/test/regression/aarch64/instructions/multiply.cc b/test/regression/aarch64/instructions/multiply.cc index 9fd2e823c2..6a7bc267f3 100644 --- a/test/regression/aarch64/instructions/multiply.cc +++ b/test/regression/aarch64/instructions/multiply.cc @@ -3,6 +3,7 @@ namespace { using InstMul = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstMul, maddw) { RUN_AARCH64(R"( @@ -41,6 +42,16 @@ TEST_P(InstMul, mulw) { mul w2, w0, w1 )"); EXPECT_EQ(getGeneralRegister(2), 42u); + + RUN_AARCH64(R"( + movz x0, #7 + movz x1, #6 + mul x2, x0, x1 + )"); + EXPECT_EQ(getGeneralRegister(2), 42u); + + EXPECT_GROUP(R"(mul w2, w0, w1)", INT_MUL); + EXPECT_GROUP(R"(mul x2, x0, x1)", INT_MUL); } TEST_P(InstMul, smaddl) { @@ -78,6 +89,8 @@ TEST_P(InstMul, smull) { smull x3, w0, w1 )"); EXPECT_EQ(getGeneralRegister(3), 0x0000002A00000000); + + EXPECT_GROUP(R"(smull x3, w0, w1)", INT_MUL); } TEST_P(InstMul, umaddl) { @@ -93,6 +106,8 @@ TEST_P(InstMul, umaddl) { )"); EXPECT_EQ(getGeneralRegister(3), 0x0005002A00000000); EXPECT_EQ(getGeneralRegister(4), 0x0000002A00000000); + + EXPECT_GROUP(R"(umull x4, w0, w1)", INT_MUL); } INSTANTIATE_TEST_SUITE_P(AArch64, InstMul, diff --git a/test/regression/aarch64/instructions/neon.cc b/test/regression/aarch64/instructions/neon.cc index e23573be9f..a4731f388f 100644 --- a/test/regression/aarch64/instructions/neon.cc +++ b/test/regression/aarch64/instructions/neon.cc @@ -5,6 +5,7 @@ namespace { using InstNeon = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstNeon, add) { // 8-bit vector @@ -3533,6 +3534,8 @@ TEST_P(InstNeon, rev) { 6, uint8_t, {0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00}); + EXPECT_GROUP(R"(rev64 v2.4h, v0.4h)", VECTOR_SIMPLE_ARTH_NOSHIFT); + // REV32 RUN_AARCH64(R"( index z0.b, #0, #1 diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index 702979b2dd..a7cee561e3 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -6,6 +6,7 @@ namespace { using InstSve = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstSve, addvl) { // 64-bits @@ -1890,6 +1891,8 @@ TEST_P(InstSve, eor) { } CHECK_PREDICATE(4, uint64_t, res_p4); + EXPECT_GROUP(R"(not p4.b, p0/z, p1.b)", PREDICATE); + // Vectors, Predicated RUN_AARCH64(R"( # 8-bit diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index a75f182fff..d96dab9bf5 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -5,13 +5,21 @@ using namespace simeng::arch::riscv; -void RISCVRegressionTest::run(const char* source, const char* extensions) { - // Initialise LLVM - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeRISCVAsmParser(); +void RISCVRegressionTest::run(const char* source, bool compressed) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(compressed); - RegressionTest::run(source, "riscv64", extensions); + RegressionTest::run(source, "riscv64", subtargetFeatures.c_str()); +} + +void RISCVRegressionTest::checkGroup( + const char* source, const std::vector& expectedGroups, + bool compressed) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(compressed); + + RegressionTest::checkGroup(source, "riscv64", subtargetFeatures.c_str(), + expectedGroups); } void RISCVRegressionTest::generateConfig() const { @@ -41,7 +49,8 @@ void RISCVRegressionTest::generateConfig() const { } std::unique_ptr -RISCVRegressionTest::createArchitecture(simeng::kernel::Linux& kernel) const { +RISCVRegressionTest::instantiateArchitecture( + simeng::kernel::Linux& kernel) const { return std::make_unique(kernel); } diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 56f8f1bcdd..a99abd5c54 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -53,49 +53,102 @@ inline std::string paramToString( return coreString; } -/** A helper macro to run a snippet of RISCV assembly code, returning from +/** A helper macro to run a snippet of RISC-V assembly code, returning from * the calling function if a fatal error occurs. Four bytes containing zeros * are appended to the source to ensure that the program will terminate with * an unallocated instruction encoding exception instead of running into the * heap. */ -#define RUN_RISCV(source) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - run(sourceWithTerminator.c_str(), "+m,+a,+f,+d"); \ - } \ +#define RUN_RISCV(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), false); \ + } \ if (HasFatalFailure()) return -/** A helper macro to run a snippet of RISCV assembly code, returning from +/** A helper macro to run a snippet of RISC-V assembly code, returning from * the calling function if a fatal error occurs. Four bytes containing zeros * are appended to the source to ensure that the program will terminate with * an illegal instruction exception instead of running into the heap. This * specifically targets the compressed extension allowing for the RUN_RISCV * macro to ignore it, otherwise LLVM eagerly emits compressed instructions for * non-compressed assembly. */ -#define RUN_RISCV_COMP(source) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - run(sourceWithTerminator.c_str(), "+m,+a,+f,+d,+c"); \ - } \ +#define RUN_RISCV_COMP(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), true); \ + } \ if (HasFatalFailure()) return -/** The test fixture for all RISCV regression tests. */ +/** A helper macro to predecode the first instruction in a snippet of RISC-V + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. + */ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, false); \ + } \ + if (HasFatalFailure()) return + +/** A helper macro to predecode the first instruction in a snippet of RISC-V + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. This specifically targets the compressed + * extension allowing for the EXPECT_GROUP macro to ignore it, otherwise LLVM + * eagerly emits compressed instructions for non-compressed assembly. */ +#define EXPECT_GROUP_COMP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, true); \ + } \ + if (HasFatalFailure()) return + +/** The test fixture for all RISC-V regression tests. */ class RISCVRegressionTest : public RegressionTest { protected: virtual ~RISCVRegressionTest() {} /** Run the assembly code in `source`. */ - void run(const char* source, const char* extensions); + void run(const char* source, bool compressed); + + /** Run the first instruction in source through predecode and check the + * groups. */ + void checkGroup(const char* source, + const std::vector& expectedGroups, bool compressed); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; - /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + /** Instantiate an ISA specific architecture from a kernel. */ + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; + /** Initialise LLVM */ + void initialiseLLVM() { + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTargetMC(); + LLVMInitializeRISCVAsmParser(); + } + + /** Get subtarget feature string. Use compressed instructions only if + * requested */ + std::string getSubtargetFeaturesString(bool compressed) { + std::string subtargetFeatures = "+m,+a,+f,+d"; + if (compressed) { + subtargetFeatures.append(",+c"); + } + return subtargetFeatures; + } + /** Get the value of a general purpose register. */ template T getGeneralRegister(uint8_t tag) const { diff --git a/test/regression/riscv/SmokeTest.cc b/test/regression/riscv/SmokeTest.cc index ee5676d0c0..c990094a9e 100644 --- a/test/regression/riscv/SmokeTest.cc +++ b/test/regression/riscv/SmokeTest.cc @@ -3,6 +3,7 @@ namespace { using SmokeTest = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; // Test that a trivial instruction will execute TEST_P(SmokeTest, instruction) { @@ -10,6 +11,7 @@ TEST_P(SmokeTest, instruction) { addi a5,a5,32 )"); EXPECT_EQ(getGeneralRegister(15), 32u); + EXPECT_GROUP(R"(addi a5,a5,32)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P( diff --git a/test/regression/riscv/instructions/arithmetic.cc b/test/regression/riscv/instructions/arithmetic.cc index 96b97acbaa..703f90133b 100644 --- a/test/regression/riscv/instructions/arithmetic.cc +++ b/test/regression/riscv/instructions/arithmetic.cc @@ -3,6 +3,7 @@ namespace { using InstArithmetic = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstArithmetic, sll) { RUN_RISCV(R"( @@ -13,6 +14,9 @@ TEST_P(InstArithmetic, sll) { )"); EXPECT_EQ(getGeneralRegister(30), 48); EXPECT_EQ(getGeneralRegister(31), 192); + + EXPECT_GROUP(R"(sll t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(slli t6, t4, 5)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sllw) { @@ -42,6 +46,9 @@ TEST_P(InstArithmetic, sllw) { EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 6); // If shamt >= 32 don't change operand as per qemu + + EXPECT_GROUP(R"(sllw t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(slliw t1, t4, 31)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, srl) { @@ -53,6 +60,9 @@ TEST_P(InstArithmetic, srl) { )"); EXPECT_EQ(getGeneralRegister(30), 15); EXPECT_EQ(getGeneralRegister(31), 7); + + EXPECT_GROUP(R"(srl t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srli t6, t4, 61)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, srlw) { @@ -70,6 +80,9 @@ TEST_P(InstArithmetic, srlw) { EXPECT_EQ(getGeneralRegister(31), 0b01111111111111111111111111111100); EXPECT_EQ(getGeneralRegister(7), -7); + + EXPECT_GROUP(R"(srlw t1, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srliw t6, t4, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sra) { @@ -86,6 +99,9 @@ TEST_P(InstArithmetic, sra) { EXPECT_EQ(getGeneralRegister(31), -2); EXPECT_EQ(getGeneralRegister(6), 1); EXPECT_EQ(getGeneralRegister(7), 2); + + EXPECT_GROUP(R"(sra t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srai t6, t4, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sraw) { @@ -113,6 +129,9 @@ TEST_P(InstArithmetic, sraw) { )"); EXPECT_EQ(getGeneralRegister(30), -1); EXPECT_EQ(getGeneralRegister(31), 1); + + EXPECT_GROUP(R"(sraw t5, t5, t2)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(sraiw t6, t6, 30)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, add) { @@ -126,6 +145,9 @@ TEST_P(InstArithmetic, add) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(30), 9u); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(add t5, t3, t4)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(addi t4, t4, 6)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, addw) { @@ -140,6 +162,8 @@ TEST_P(InstArithmetic, addw) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(30), 9u); EXPECT_EQ(getGeneralRegister(31), -4); + + EXPECT_GROUP(R"(addw t5, t3, t4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, addiw) { @@ -154,6 +178,8 @@ TEST_P(InstArithmetic, addiw) { EXPECT_EQ(getGeneralRegister(29), -5); EXPECT_EQ(getGeneralRegister(30), -1342177285); EXPECT_EQ(getGeneralRegister(31), -5); + + EXPECT_GROUP(R"(addiw t5, t3, -5)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, sub) { @@ -165,6 +191,8 @@ TEST_P(InstArithmetic, sub) { )"); EXPECT_EQ(getGeneralRegister(30), -3); EXPECT_EQ(getGeneralRegister(31), 3); + + EXPECT_GROUP(R"(sub t6, t4, t3)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, subw) { @@ -185,6 +213,8 @@ TEST_P(InstArithmetic, subw) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(29), -2); EXPECT_EQ(getGeneralRegister(6), 0x0000000000000001); + + EXPECT_GROUP(R"(subw t1, t3, t4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, lui) { @@ -194,6 +224,8 @@ TEST_P(InstArithmetic, lui) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), -4ull << 12); + + EXPECT_GROUP(R"(lui t3, 4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, auipc) { @@ -203,6 +235,8 @@ TEST_P(InstArithmetic, auipc) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), (-4ull << 12) + 4); + + EXPECT_GROUP(R"(auipc t4, 1048572)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, xor) { @@ -224,6 +258,10 @@ TEST_P(InstArithmetic, xor) { not t1, t3 )"); EXPECT_EQ(getGeneralRegister(6), -4); + + EXPECT_GROUP(R"(xor t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(xori t6, t5, 5)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(not t1, t3)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, or) { @@ -237,6 +275,9 @@ TEST_P(InstArithmetic, or) { EXPECT_EQ(getGeneralRegister(30), 0b0111); EXPECT_EQ(getGeneralRegister(31), 0b1111); EXPECT_EQ(getGeneralRegister(7), -5); + + EXPECT_GROUP(R"(or t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(ori t6, t5, 9)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, and) { @@ -250,6 +291,9 @@ TEST_P(InstArithmetic, and) { EXPECT_EQ(getGeneralRegister(30), 0b0001); EXPECT_EQ(getGeneralRegister(31), 0b0001); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(and t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(andi t6, t5, 9)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, slt) { @@ -265,6 +309,9 @@ TEST_P(InstArithmetic, slt) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(slt t6, t4, t3)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltu t1, t3, t4)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, slti) { @@ -280,6 +327,9 @@ TEST_P(InstArithmetic, slti) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(slti t6, t4, -3)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltiu t1, t3, 5)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, addiPseudoinstructions) { @@ -295,6 +345,10 @@ TEST_P(InstArithmetic, addiPseudoinstructions) { EXPECT_EQ(getGeneralRegister(0), 0); EXPECT_EQ(getGeneralRegister(28), -5); EXPECT_EQ(getGeneralRegister(29), -5); + + EXPECT_GROUP(R"(nop)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(mv t2, t1)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(sext.w t4, t3)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, subwPseudoinstructions) { @@ -311,6 +365,9 @@ TEST_P(InstArithmetic, subwPseudoinstructions) { EXPECT_EQ(getGeneralRegister(30), 48586817536); EXPECT_EQ(getGeneralRegister(7), 1342177280); EXPECT_EQ(getGeneralRegister(31), -1342177280); + + EXPECT_GROUP(R"(neg t4, t3)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(negw t6, t5)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, setPseudoinstructions) { @@ -342,6 +399,11 @@ TEST_P(InstArithmetic, setPseudoinstructions) { EXPECT_EQ(getGeneralRegister(30), 0); EXPECT_EQ(getGeneralRegister(8), 1); EXPECT_EQ(getGeneralRegister(9), 0); + + EXPECT_GROUP(R"(seqz t3, t1)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(snez t4, t0)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltz t4, t6)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sgtz t5, t0)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, liPseudoinstruction) { @@ -356,6 +418,8 @@ TEST_P(InstArithmetic, liPseudoinstruction) { EXPECT_EQ(getGeneralRegister(15), 0); EXPECT_EQ(getGeneralRegister(14), 192); EXPECT_EQ(getGeneralRegister(13), -180); + + EXPECT_GROUP(R"(li a5, 0)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstArithmetic, diff --git a/test/regression/riscv/instructions/atomic.cc b/test/regression/riscv/instructions/atomic.cc index 9f21d7abf1..d8b0bc6151 100644 --- a/test/regression/riscv/instructions/atomic.cc +++ b/test/regression/riscv/instructions/atomic.cc @@ -3,6 +3,17 @@ namespace { using InstAtomic = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; + +// Whilst most RISC-V atomic instructions perform read-modify-write operations +// i.e. a load, comparison and store, each is given the group LOAD_INT only. The +// instruction object is tagged with the appropriate identifiers (isLoad, +// isStore and isAtomic) but the group only reflects the first stage of +// execution. This ensures the instruction goes to the correct part of the +// pipeline i.e. the LSQ. But we currently do not model the rest of the atomic +// behaviour precisely as the comparison happens here also. The change of the +// instructions behaviour over its lifetime is currently not reflected in the +// group it is given. TEST_P(InstAtomic, lr) { initialHeapData_.resize(16); @@ -20,11 +31,12 @@ TEST_P(InstAtomic, lr) { lr.w t6, (a0) addi a0, a0, 4 lr.w t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -33,11 +45,12 @@ TEST_P(InstAtomic, lr) { lr.w.aq t6, (a0) addi a0, a0, 4 lr.w.aq t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.aq t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -46,11 +59,12 @@ TEST_P(InstAtomic, lr) { lr.w.aqrl t6, (a0) addi a0, a0, 4 lr.w.aqrl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.aqrl t5, (a0))", LOAD_INT); + // Software should not set only the RL bit, but this is not guaranteed RUN_RISCV(R"( # Get heap address @@ -60,11 +74,12 @@ TEST_P(InstAtomic, lr) { lr.w.rl t6, (a0) addi a0, a0, 4 lr.w.rl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.rl t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -73,11 +88,12 @@ TEST_P(InstAtomic, lr) { lr.d t6, (a0) addi a0, a0, 4 lr.d t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -86,11 +102,12 @@ TEST_P(InstAtomic, lr) { lr.d.aq t6, (a0) addi a0, a0, 4 lr.d.aq t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d.aq t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -99,11 +116,12 @@ TEST_P(InstAtomic, lr) { lr.d.aqrl t6, (a0) addi a0, a0, 4 lr.d.aqrl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d.aqrl t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -112,10 +130,11 @@ TEST_P(InstAtomic, lr) { lr.d.rl t6, (a0) addi a0, a0, 4 lr.d.rl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + + EXPECT_GROUP(R"(lr.d.rl t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, sc_w) { @@ -142,6 +161,8 @@ TEST_P(InstAtomic, sc_w) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_aq) { @@ -170,6 +191,8 @@ TEST_P(InstAtomic, sc_w_aq) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.aq t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_rl) { @@ -196,6 +219,8 @@ TEST_P(InstAtomic, sc_w_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.rl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_aq_rl) { @@ -222,6 +247,8 @@ TEST_P(InstAtomic, sc_w_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.aqrl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d) { @@ -252,6 +279,8 @@ TEST_P(InstAtomic, sc_d) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_aq) { @@ -282,6 +311,8 @@ TEST_P(InstAtomic, sc_d_aq) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.aq t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_rl) { @@ -312,6 +343,8 @@ TEST_P(InstAtomic, sc_d_rl) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.rl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_aq_rl) { @@ -342,6 +375,8 @@ TEST_P(InstAtomic, sc_d_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.aqrl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, amoswap_w) { @@ -380,6 +415,8 @@ TEST_P(InstAtomic, amoswap_w) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_aq) { @@ -418,6 +455,8 @@ TEST_P(InstAtomic, amoswap_w_aq) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_rl) { @@ -456,6 +495,8 @@ TEST_P(InstAtomic, amoswap_w_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_aq_rl) { @@ -494,6 +535,8 @@ TEST_P(InstAtomic, amoswap_w_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.aqrl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d) { @@ -539,6 +582,8 @@ TEST_P(InstAtomic, amoswap_d) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_aq) { @@ -584,6 +629,8 @@ TEST_P(InstAtomic, amoswap_d_aq) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_rl) { @@ -629,6 +676,8 @@ TEST_P(InstAtomic, amoswap_d_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_aq_rl) { @@ -674,6 +723,8 @@ TEST_P(InstAtomic, amoswap_d_aq_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.aqrl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w) { @@ -717,6 +768,8 @@ TEST_P(InstAtomic, amoadd_w) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_aq) { @@ -760,6 +813,8 @@ TEST_P(InstAtomic, amoadd_w_aq) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_rl) { @@ -803,6 +858,8 @@ TEST_P(InstAtomic, amoadd_w_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_aq_rl) { @@ -846,6 +903,8 @@ TEST_P(InstAtomic, amoadd_w_aq_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.aqrl t5, t6, (a0))", LOAD_INT); } // TODO add aq rl tests for all instructions below, omitted as currently @@ -891,6 +950,8 @@ TEST_P(InstAtomic, amoadd_d) { 0x80000000000003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 20), 0x12365478); // +ve + +ve = -ve as per GDB + + EXPECT_GROUP(R"(amoadd.d t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoand_w) { @@ -919,6 +980,8 @@ TEST_P(InstAtomic, amoand_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x1234567811111111); // 0b0001 + + EXPECT_GROUP(R"(amoand.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoand_d) { @@ -948,6 +1011,8 @@ TEST_P(InstAtomic, amoand_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x1111111111111111); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoand.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoor_w) { @@ -976,6 +1041,8 @@ TEST_P(InstAtomic, amoor_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x12345678F7777777); // 0b0111 + + EXPECT_GROUP(R"(amoor.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoor_d) { @@ -1005,6 +1072,8 @@ TEST_P(InstAtomic, amoor_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x7777777777777777); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoor.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoxor_w) { @@ -1033,6 +1102,8 @@ TEST_P(InstAtomic, amoxor_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x12345678E6666666); // 0b0110 + + EXPECT_GROUP(R"(amoxor.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoxor_d) { @@ -1062,6 +1133,8 @@ TEST_P(InstAtomic, amoxor_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x6666666666666666); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoxor.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomin_w) { @@ -1141,6 +1214,8 @@ TEST_P(InstAtomic, amomin_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567803333333); + + EXPECT_GROUP(R"(amomin.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomin_d) { @@ -1180,6 +1255,8 @@ TEST_P(InstAtomic, amomin_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x0034567899999999); + + EXPECT_GROUP(R"(amomin.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amominu_w) { @@ -1260,6 +1337,8 @@ TEST_P(InstAtomic, amominu_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567803333333); + + EXPECT_GROUP(R"(amominu.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amominu_d) { @@ -1300,6 +1379,8 @@ TEST_P(InstAtomic, amominu_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x0034567899999999); + + EXPECT_GROUP(R"(amominu.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomax_w) { @@ -1379,6 +1460,8 @@ TEST_P(InstAtomic, amomax_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567855555555); + + EXPECT_GROUP(R"(amomax.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomax_d) { @@ -1418,6 +1501,8 @@ TEST_P(InstAtomic, amomax_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x12345678FEEBDAED); + + EXPECT_GROUP(R"(amomax.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomaxu_w) { @@ -1498,6 +1583,8 @@ TEST_P(InstAtomic, amomaxu_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567855555555); + + EXPECT_GROUP(R"(amomaxu.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomaxu_d) { @@ -1537,6 +1624,8 @@ TEST_P(InstAtomic, amomaxu_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 8), 0x12345678FEEBDAED); + + EXPECT_GROUP(R"(amomaxu.d t6, t5, (a0))", LOAD_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstAtomic, diff --git a/test/regression/riscv/instructions/branch.cc b/test/regression/riscv/instructions/branch.cc index 16b067f4f1..a31effb676 100644 --- a/test/regression/riscv/instructions/branch.cc +++ b/test/regression/riscv/instructions/branch.cc @@ -3,6 +3,7 @@ namespace { using InstBranch = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstBranch, BEQ) { RUN_RISCV(R"( @@ -23,6 +24,9 @@ TEST_P(InstBranch, BEQ) { EXPECT_EQ(getGeneralRegister(29), 7); EXPECT_EQ(getGeneralRegister(28), 5); EXPECT_EQ(getGeneralRegister(7), 0); + + EXPECT_GROUP(R"(beq zero, t4, 8)", BRANCH); + EXPECT_GROUP(R"(beqz s0, -8)", BRANCH); } TEST_P(InstBranch, BNE) { @@ -41,6 +45,9 @@ TEST_P(InstBranch, BNE) { EXPECT_EQ(getGeneralRegister(31), 7); EXPECT_EQ(getGeneralRegister(29), 19); EXPECT_EQ(getGeneralRegister(28), 17); + + EXPECT_GROUP(R"(bne t0, t1, 8)", BRANCH); + EXPECT_GROUP(R"(bnez t0, 4)", BRANCH); } TEST_P(InstBranch, BLT) { @@ -63,6 +70,9 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(7), 17); + EXPECT_GROUP(R"(blt t0, t1, 8)", BRANCH); + EXPECT_GROUP(R"(bltz t4, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -79,6 +89,8 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(29), 13); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(bgtz t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -94,6 +106,8 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(31), 18); EXPECT_EQ(getGeneralRegister(29), 13); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(bgt t1, t0, 8 )", BRANCH); } TEST_P(InstBranch, BLTU) { @@ -112,6 +126,9 @@ TEST_P(InstBranch, BLTU) { EXPECT_EQ(getGeneralRegister(31), 7); EXPECT_EQ(getGeneralRegister(29), 16); EXPECT_EQ(getGeneralRegister(28), 15); + + EXPECT_GROUP(R"(bltu t1, t0, 8)", BRANCH); + EXPECT_GROUP(R"(bgtu t1, t0, 8)", BRANCH); } TEST_P(InstBranch, BGE) { @@ -130,6 +147,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_GROUP(R"(bge t1, t0, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -146,6 +165,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(blez t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -162,6 +183,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(bgez t3, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -177,6 +200,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(31), 18); EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(ble t3, t3, 8)", BRANCH); } TEST_P(InstBranch, BGEU) { @@ -198,6 +223,8 @@ TEST_P(InstBranch, BGEU) { EXPECT_EQ(getGeneralRegister(28), 14); EXPECT_EQ(getGeneralRegister(7), 11); + EXPECT_GROUP(R"(bgeu t0, t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -213,6 +240,8 @@ TEST_P(InstBranch, BGEU) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(bleu t3, t3, 8)", BRANCH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstBranch, diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 90335b1d7d..a7387e09b4 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -3,6 +3,7 @@ namespace { using InstCompressed = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstCompressed, lwsp) { // Load word from mem[stack pointer + imm] @@ -24,6 +25,8 @@ TEST_P(InstCompressed, lwsp) { )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(29), 0x0000000012345678); + + EXPECT_GROUP_COMP(R"(c.lwsp t4, 4(x2))", LOAD_INT); } TEST_P(InstCompressed, ldsp) { @@ -47,6 +50,8 @@ TEST_P(InstCompressed, ldsp) { )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); + + EXPECT_GROUP_COMP(R"(c.ldsp t4, 8(x2))", LOAD_INT); } TEST_P(InstCompressed, fldsp) { @@ -75,6 +80,8 @@ TEST_P(InstCompressed, fldsp) { EXPECT_EQ(getFPRegister(1), 123.456); EXPECT_EQ(getFPRegister(2), -0.00032); EXPECT_EQ(getFPRegister(3), 123456); + + EXPECT_GROUP_COMP(R"(c.fldsp ft3, 24(x2))", LOAD_FLOAT); } TEST_P(InstCompressed, swsp) { @@ -92,6 +99,8 @@ TEST_P(InstCompressed, swsp) { 0x000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x15400AA000000AA); + + EXPECT_GROUP_COMP(R"(c.swsp t6, 4(sp))", STORE_INT); } TEST_P(InstCompressed, sdsp) { @@ -109,6 +118,8 @@ TEST_P(InstCompressed, sdsp) { 0x00000000000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.sdsp t6, 8(sp))", STORE_INT); } TEST_P(InstCompressed, fsdsp) { @@ -128,6 +139,8 @@ TEST_P(InstCompressed, fsdsp) { 0x00000000000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.fsdsp f8, 8(sp))", STORE_FLOAT); } TEST_P(InstCompressed, lw) { @@ -149,6 +162,8 @@ TEST_P(InstCompressed, lw) { )"); EXPECT_EQ(getGeneralRegister(15), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(13), 0x0000000012345678); + + EXPECT_GROUP_COMP(R"(c.lw x13, 4(x8))", LOAD_INT); } TEST_P(InstCompressed, ld) { @@ -171,6 +186,8 @@ TEST_P(InstCompressed, ld) { )"); EXPECT_EQ(getGeneralRegister(15), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(13), 0xFEEBDAED12345678); + + EXPECT_GROUP_COMP(R"(c.ld x13, 8(x8))", LOAD_INT); } TEST_P(InstCompressed, fld) { @@ -197,6 +214,8 @@ TEST_P(InstCompressed, fld) { EXPECT_EQ(getFPRegister(9), 123.456); EXPECT_EQ(getFPRegister(10), -0.00032); EXPECT_EQ(getFPRegister(11), 123456); + + EXPECT_GROUP_COMP(R"(c.fld f11, 24(a0))", LOAD_FLOAT); } TEST_P(InstCompressed, sw) { @@ -224,6 +243,8 @@ TEST_P(InstCompressed, sw) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(32), 0x015400AA000000AA); EXPECT_EQ(getMemoryValue(36), 0x87654321015400AA); + + EXPECT_GROUP_COMP(R"(c.sw x8, 4(a0))", STORE_INT); } TEST_P(InstCompressed, sd) { @@ -251,6 +272,8 @@ TEST_P(InstCompressed, sd) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(32), 0x00000000000000AA); EXPECT_EQ(getMemoryValue(40), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.sd x8, 8(a0))", STORE_INT); } TEST_P(InstCompressed, fsd) { @@ -289,6 +312,8 @@ TEST_P(InstCompressed, fsd) { EXPECT_EQ(getMemoryValue(40), -0.00032); EXPECT_EQ(getMemoryValue(48), 123.456); EXPECT_EQ(getMemoryValue(56), 1.0); + + EXPECT_GROUP_COMP(R"(c.fsd fa3, 0(a0))", STORE_FLOAT); } TEST_P(InstCompressed, j) { @@ -313,6 +338,8 @@ TEST_P(InstCompressed, j) { EXPECT_EQ(getGeneralRegister(6), 8); EXPECT_EQ(getGeneralRegister(1), 14); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP_COMP(R"(c.j jump)", BRANCH); } TEST_P(InstCompressed, jr) { @@ -326,6 +353,8 @@ TEST_P(InstCompressed, jr) { end: )"); EXPECT_EQ(getGeneralRegister(8), 5); + + EXPECT_GROUP_COMP(R"(c.jr x9)", BRANCH); } TEST_P(InstCompressed, jalr) { @@ -351,6 +380,8 @@ TEST_P(InstCompressed, jalr) { EXPECT_EQ(getGeneralRegister(6), 4); EXPECT_EQ(getGeneralRegister(7), 12); EXPECT_EQ(getGeneralRegister(1), 12); + + EXPECT_GROUP_COMP(R"(c.jalr x8)", BRANCH); } TEST_P(InstCompressed, beqz) { @@ -373,6 +404,8 @@ TEST_P(InstCompressed, beqz) { )"); EXPECT_EQ(getGeneralRegister(10), 10); EXPECT_EQ(getGeneralRegister(11), 10); + + EXPECT_GROUP_COMP(R"(c.beqz x9, b2)", BRANCH); } TEST_P(InstCompressed, bnez) { @@ -393,6 +426,8 @@ TEST_P(InstCompressed, bnez) { addi x11, x11, 5 b4: )"); + + EXPECT_GROUP_COMP(R"(c.bnez x9, b2)", BRANCH); } TEST_P(InstCompressed, li) { @@ -408,6 +443,8 @@ TEST_P(InstCompressed, li) { EXPECT_EQ(getGeneralRegister(15), 0); EXPECT_EQ(getGeneralRegister(14), -32); EXPECT_EQ(getGeneralRegister(13), 31); + + EXPECT_GROUP_COMP(R"(c.li a3, 31)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, lui) { @@ -419,6 +456,8 @@ TEST_P(InstCompressed, lui) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), -4ull << 12); + + EXPECT_GROUP_COMP(R"(c.lui t4, 0xFFFFC)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi) { @@ -432,6 +471,8 @@ TEST_P(InstCompressed, addi) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(28), 33u); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP_COMP(R"(c.addi zero, 16)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addiw) { @@ -445,6 +486,8 @@ TEST_P(InstCompressed, addiw) { EXPECT_EQ(getGeneralRegister(28), 24427626496); EXPECT_EQ(getGeneralRegister(30), -1342177285); EXPECT_EQ(getGeneralRegister(31), -5); + + EXPECT_GROUP_COMP(R"(addiw t6, t2, -5)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi16sp) { @@ -458,6 +501,8 @@ TEST_P(InstCompressed, addi16sp) { process_->getInitialStackPointer()); EXPECT_EQ(getGeneralRegister(9), process_->getInitialStackPointer() + 16); + + EXPECT_GROUP_COMP(R"(mv x9, x2)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi4spn) { @@ -470,6 +515,8 @@ TEST_P(InstCompressed, addi4spn) { process_->getInitialStackPointer() + 4); EXPECT_EQ(getGeneralRegister(9), process_->getInitialStackPointer() + 12); + + EXPECT_GROUP_COMP(R"(c.addi4spn x9, x2, 12)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, slli) { @@ -479,6 +526,8 @@ TEST_P(InstCompressed, slli) { c.slli t4, 5 )"); EXPECT_EQ(getGeneralRegister(29), 192); + + EXPECT_GROUP_COMP(R"(c.slli t4, 5)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, srli) { @@ -488,6 +537,8 @@ TEST_P(InstCompressed, srli) { c.srli x8, 61 )"); EXPECT_EQ(getGeneralRegister(8), 7); + + EXPECT_GROUP_COMP(R"(c.srli x8, 61)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, srai) { @@ -501,6 +552,8 @@ TEST_P(InstCompressed, srai) { )"); EXPECT_EQ(getGeneralRegister(8), -2); EXPECT_EQ(getGeneralRegister(9), 2); + + EXPECT_GROUP_COMP(R"(c.srai x9, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, andi) { @@ -514,6 +567,8 @@ TEST_P(InstCompressed, andi) { )"); EXPECT_EQ(getGeneralRegister(8), 0b0001); EXPECT_EQ(getGeneralRegister(9), 1); + + EXPECT_GROUP_COMP(R"(c.andi x9, -7)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, mv) { @@ -525,6 +580,8 @@ TEST_P(InstCompressed, mv) { )"); EXPECT_EQ(getGeneralRegister(8), 6u); EXPECT_EQ(getGeneralRegister(9), 6u); + + EXPECT_GROUP_COMP(R"(c.mv x8, x9)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, add) { @@ -536,6 +593,8 @@ TEST_P(InstCompressed, add) { )"); EXPECT_EQ(getGeneralRegister(8), 9u); EXPECT_EQ(getGeneralRegister(9), 6u); + + EXPECT_GROUP_COMP(R"(c.add x8, x9)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, and) { @@ -546,6 +605,8 @@ TEST_P(InstCompressed, and) { c.and x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0001); + + EXPECT_GROUP_COMP(R"(c.and x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, or) { @@ -556,6 +617,8 @@ TEST_P(InstCompressed, or) { c.or x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0111); + + EXPECT_GROUP_COMP(R"(c.or x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, xor) { @@ -566,6 +629,8 @@ TEST_P(InstCompressed, xor) { c.xor x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0110); + + EXPECT_GROUP_COMP(R"(c.xor x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, sub) { @@ -579,6 +644,8 @@ TEST_P(InstCompressed, sub) { )"); EXPECT_EQ(getGeneralRegister(8), -3); EXPECT_EQ(getGeneralRegister(9), 3); + + EXPECT_GROUP_COMP(R"(c.sub x9, x10)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addw) { @@ -594,6 +661,8 @@ TEST_P(InstCompressed, addw) { )"); EXPECT_EQ(getGeneralRegister(8), 9u); EXPECT_EQ(getGeneralRegister(9), -4); + + EXPECT_GROUP_COMP(R"(c.addw x9, x11)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, subw) { @@ -616,6 +685,8 @@ TEST_P(InstCompressed, subw) { EXPECT_EQ(getGeneralRegister(11), -2); EXPECT_EQ(getGeneralRegister(12), 0x0000000000000001); + + EXPECT_GROUP_COMP(R"(c.subw x12, x11)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, nop) { @@ -705,6 +776,8 @@ TEST_P(InstCompressed, nop) { EXPECT_EQ(getGeneralRegister(30), 0); EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(numTicks_, 6); // 5 insns + 1 for unimplemented final insn + + EXPECT_GROUP_COMP(R"(c.nop)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, ebreak) { @@ -719,6 +792,8 @@ TEST_P(InstCompressed, ebreak) { "exception\n[SimEng:ExceptionHandler] Generated by instruction: " "\n[SimEng:ExceptionHandler] 0x0000000000000000: 02 90 c.ebreak"; EXPECT_EQ(stdout_.substr(0, sizeof(err1) - 1), err1); + + EXPECT_GROUP_COMP(R"(c.ebreak)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P( diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc index 232e56f551..d5c910d53b 100644 --- a/test/regression/riscv/instructions/float.cc +++ b/test/regression/riscv/instructions/float.cc @@ -3,6 +3,7 @@ namespace { using InstFloat = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; static constexpr uint64_t boxedPositiveNan = 0xffffffff7fc00000; @@ -31,6 +32,8 @@ TEST_P(InstFloat, FLD) { EXPECT_EQ(getFPRegister(1), 123.456); EXPECT_EQ(getFPRegister(2), -0.00032); EXPECT_EQ(getFPRegister(3), 123456); + + EXPECT_GROUP(R"(fld ft3, 24(a0))", LOAD_FLOAT); } TEST_P(InstFloat, FLW) { @@ -70,6 +73,8 @@ TEST_P(InstFloat, FLW) { EXPECT_EQ(getFPRegister(1), 0xffffffff42f6e979); EXPECT_EQ(getFPRegister(2), 0xffffffffb9a7c5ac); EXPECT_EQ(getFPRegister(3), 0xffffffff47f12000); + + EXPECT_GROUP(R"( flw ft3, 12(a0))", LOAD_FLOAT); } TEST_P(InstFloat, FSD) { @@ -107,6 +112,8 @@ TEST_P(InstFloat, FSD) { EXPECT_EQ(getMemoryValue(72), -0.00032); EXPECT_EQ(getMemoryValue(80), 123.456); EXPECT_EQ(getMemoryValue(88), 1.0); + + EXPECT_GROUP(R"(fsd ft0, 24(a0))", STORE_FLOAT); } TEST_P(InstFloat, FSW) { @@ -146,6 +153,8 @@ TEST_P(InstFloat, FSW) { EXPECT_EQ(getMemoryValue(68), (float)-0.00032); EXPECT_EQ(getMemoryValue(72), (float)123.456); EXPECT_EQ(getMemoryValue(76), (float)1.0); + + EXPECT_GROUP(R"(fsw ft0, 12(a0))", STORE_FLOAT); } TEST_P(InstFloat, FDIV_D) { @@ -174,6 +183,8 @@ TEST_P(InstFloat, FDIV_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (double)999.212341 / (double)4.52432537); EXPECT_EQ(getFPRegister(0), (double)999.212341 / (double)-3.78900003); + + EXPECT_GROUP(R"(fdiv.d ft0, fa5, fa4)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FDIV_S) { @@ -226,6 +237,8 @@ TEST_P(InstFloat, FDIV_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fdiv.s ft0, fa5, fa4)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FMUL_D) { @@ -254,6 +267,8 @@ TEST_P(InstFloat, FMUL_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (double)999.212341 * (double)4.52432537); EXPECT_EQ(getFPRegister(0), (double)999.212341 * (double)-3.78900003); + + EXPECT_GROUP(R"(fmul.d ft0, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FMUL_S) { @@ -307,6 +322,8 @@ TEST_P(InstFloat, FMUL_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmul.s ft0, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FCVT_D_L) { @@ -325,6 +342,8 @@ TEST_P(InstFloat, FCVT_D_L) { EXPECT_EQ(getFPRegister(0), 0x405EC00000000000); EXPECT_EQ(getFPRegister(1), (double)-1); EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); + + EXPECT_GROUP(R"(fcvt.d.l ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_W) { @@ -348,6 +367,8 @@ TEST_P(InstFloat, FCVT_D_W) { EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); EXPECT_EQ(getFPRegister(2), (double)268435455); EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); + + EXPECT_GROUP(R"(fcvt.d.w ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_L) { @@ -371,6 +392,8 @@ TEST_P(InstFloat, FCVT_S_L) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); EXPECT_EQ(getFPRegister(2), (float)-4026531841); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFFCF700000); + + EXPECT_GROUP(R"(fcvt.s.l ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_W) { @@ -394,6 +417,8 @@ TEST_P(InstFloat, FCVT_S_W) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); EXPECT_EQ(getFPRegister(2), (float)268435455); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4d800000); + + EXPECT_GROUP(R"(fcvt.s.w ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_W_D) { @@ -434,6 +459,8 @@ TEST_P(InstFloat, FCVT_W_D) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); EXPECT_EQ(getGeneralRegister(7), 0x000000007FFFFFFF); + + EXPECT_GROUP(R"(fcvt.w.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_W_S) { @@ -496,6 +523,8 @@ TEST_P(InstFloat, FCVT_W_S) { EXPECT_EQ(getGeneralRegister(6), pow(2, 31) - 1); // Expected result from spec EXPECT_EQ(getGeneralRegister(6), 0x000000007fffffff); + + EXPECT_GROUP(R"(fcvt.w.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_L_D) { @@ -532,6 +561,8 @@ TEST_P(InstFloat, FCVT_L_D) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); EXPECT_EQ(getGeneralRegister(7), 0x7FFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.l.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_L_S) { @@ -593,6 +624,8 @@ TEST_P(InstFloat, FCVT_L_S) { EXPECT_EQ(getGeneralRegister(5), 0x0000000000000001); EXPECT_EQ(getGeneralRegister(6), (uint64_t)pow(2, 63) - 1); // Expected result from spec + + EXPECT_GROUP(R"(fcvt.l.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_LU_D) { @@ -632,6 +665,8 @@ TEST_P(InstFloat, FCVT_LU_D) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.lu.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_WU_D) { @@ -671,6 +706,8 @@ TEST_P(InstFloat, FCVT_WU_D) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.wu.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_LU_S) { @@ -735,6 +772,8 @@ TEST_P(InstFloat, FCVT_LU_S) { EXPECT_EQ(getGeneralRegister(5), 0x0000000000000001); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFF); // Expected result from spec + + EXPECT_GROUP(R"(fcvt.lu.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_WU_S) { @@ -800,6 +839,8 @@ TEST_P(InstFloat, FCVT_WU_S) { EXPECT_EQ(getGeneralRegister(6), pow(2, 32) - 1); // Expected result from spec EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.wu.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_WU) { @@ -823,6 +864,8 @@ TEST_P(InstFloat, FCVT_D_WU) { EXPECT_EQ(getFPRegister(1), 0x41EFFFFFFFE00000); EXPECT_EQ(getFPRegister(2), (double)268435455); EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); + + EXPECT_GROUP(R"(fcvt.d.wu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_WU) { @@ -846,6 +889,8 @@ TEST_P(InstFloat, FCVT_S_WU) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF4F800000); EXPECT_EQ(getFPRegister(2), (float)268435456); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4D800000); + + EXPECT_GROUP(R"(fcvt.s.wu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_LU) { @@ -869,6 +914,8 @@ TEST_P(InstFloat, FCVT_D_LU) { EXPECT_EQ(getFPRegister(1), 0x43F0000000000000); EXPECT_EQ(getFPRegister(2), (double)1.8446744069683019776e+19); EXPECT_EQ(getFPRegister(2), 0x43EFFFFFFFE20000); + + EXPECT_GROUP(R"(fcvt.d.lu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_LU) { @@ -892,6 +939,8 @@ TEST_P(InstFloat, FCVT_S_LU) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF5F800000); EXPECT_EQ(getFPRegister(2), (float)1.84467440737e+19); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF5F800000); + + EXPECT_GROUP(R"(fcvt.s.lu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FMADD_D) { @@ -920,6 +969,8 @@ TEST_P(InstFloat, FMADD_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (4.52432537 * 999.212341) + -3.78900003); EXPECT_EQ(getFPRegister(17), (999.212341 * -3.78900003) + 4.52432537); + + EXPECT_GROUP(R"(fmadd.d fa6, fa3, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FMADD_S) { @@ -979,6 +1030,8 @@ TEST_P(InstFloat, FMADD_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fmadd.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMSUB_D) { @@ -1006,6 +1059,8 @@ TEST_P(InstFloat, FNMSUB_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), -(999.212341 * -3.78900003) + 4.52432537); + + EXPECT_GROUP(R"(fnmsub.d fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FNMSUB_S) { @@ -1062,6 +1117,8 @@ TEST_P(InstFloat, FNMSUB_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fnmsub.s fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FMSUB_S) { @@ -1121,6 +1178,8 @@ TEST_P(InstFloat, FMSUB_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fmsub.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FMSUB_D) { @@ -1153,6 +1212,8 @@ TEST_P(InstFloat, FMSUB_D) { (double)-3790.5399153953703716979362070560455322265625); EXPECT_EQ(getFPRegister(16), 0xC0AD9D146FCA6B72); EXPECT_EQ(getFPRegister(17), 0xC08FC2D70F769B06); + + EXPECT_GROUP(R"(fmsub.d fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMADD_S) { @@ -1212,6 +1273,8 @@ TEST_P(InstFloat, FNMADD_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fnmadd.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMADD_D) { @@ -1244,6 +1307,8 @@ TEST_P(InstFloat, FNMADD_D) { (double)3781.4912646553702870733104646205902099609375); EXPECT_EQ(getFPRegister(16), 0x40AD8AFB870A78FE); EXPECT_EQ(getFPRegister(17), 0xC08EB08EB0368E94); + + EXPECT_GROUP(R"(fnmadd.d fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FCVT_D_S) { @@ -1308,6 +1373,8 @@ TEST_P(InstFloat, FCVT_D_S) { EXPECT_EQ(getFPRegister(0), 0x3FF0000000000000); EXPECT_EQ(getFPRegister(1), 0x7FF8000000000000); + + EXPECT_GROUP(R"(fcvt.d.s ft0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_D) { @@ -1346,6 +1413,8 @@ TEST_P(InstFloat, FCVT_S_D) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFc0727efa); EXPECT_EQ(getFPRegister(2), (float)999.212341); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4479cd97); + + EXPECT_GROUP(R"(fcvt.s.d ft0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FSGNJ_D) { @@ -1397,6 +1466,9 @@ TEST_P(InstFloat, FSGNJ_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)-3.78900003); EXPECT_EQ(getFPRegister(3), (double)4.52432537); + + EXPECT_GROUP(R"(fsgnj.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fmv.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJ_S) { @@ -1476,6 +1548,9 @@ TEST_P(InstFloat, FSGNJ_S) { EXPECT_EQ(getFPRegister(0), 0xffffffffbf800000); EXPECT_EQ(getFPRegister(1), 0xffffffffffc00000); EXPECT_EQ(getFPRegister(2), 0xffffffff3f800000); + + EXPECT_GROUP(R"(fsgnj.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fmv.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJX_D) { @@ -1527,6 +1602,9 @@ TEST_P(InstFloat, FSGNJX_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)3.78900003); EXPECT_EQ(getFPRegister(3), (double)4.52432537); + + EXPECT_GROUP(R"(fsgnjx.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fabs.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJX_S) { @@ -1604,6 +1682,9 @@ TEST_P(InstFloat, FSGNJX_S) { EXPECT_EQ(getFPRegister(0), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(1), 0xffffffffffc00000); EXPECT_EQ(getFPRegister(2), 0xffffffffbf800000); + + EXPECT_GROUP(R"(fsgnjx.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fabs.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJN_D) { @@ -1656,6 +1737,9 @@ TEST_P(InstFloat, FSGNJN_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)3.78900003); EXPECT_EQ(getFPRegister(3), (double)-4.52432537); + + EXPECT_GROUP(R"(fsgnjn.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fneg.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJN_S) { @@ -1734,6 +1818,9 @@ TEST_P(InstFloat, FSGNJN_S) { EXPECT_EQ(getFPRegister(0), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(1), boxedPositiveNan); EXPECT_EQ(getFPRegister(2), 0xffffffffbf800000); + + EXPECT_GROUP(R"(fsgnjn.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fneg.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FADD_S) { @@ -1789,6 +1876,8 @@ TEST_P(InstFloat, FADD_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff40000000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fadd.s ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FADD_D) { @@ -1815,6 +1904,8 @@ TEST_P(InstFloat, FADD_D) { EXPECT_EQ(getFPRegister(4), 124.456); EXPECT_EQ(getFPRegister(5), 123.456 - 0.00032); + + EXPECT_GROUP(R"(fadd.d ft4, ft0, ft1)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSUB_D) { @@ -1844,6 +1935,8 @@ TEST_P(InstFloat, FSUB_D) { EXPECT_EQ(getFPRegister(0), (double)-8.3133254); EXPECT_EQ(getFPRegister(1), (double)8.3133254); + + EXPECT_GROUP(R"(fsub.d ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSUB_S) { @@ -1899,6 +1992,8 @@ TEST_P(InstFloat, FSUB_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff00000000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fsub.s ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSQRT_D) { @@ -1933,6 +2028,8 @@ TEST_P(InstFloat, FSQRT_D) { EXPECT_EQ(getFPRegister(1), 0x7FF8000000000000); // NaN EXPECT_EQ(getFPRegister(2), (double)0.067289611417595679432324118352); EXPECT_EQ(getFPRegister(2), 0x3FB139E458662CD6); + + EXPECT_GROUP(R"(fsqrt.d ft0, fa5)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FSQRT_S) { @@ -1991,6 +2088,8 @@ TEST_P(InstFloat, FSQRT_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fsqrt.s ft0, fa5)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FMV_X_D) { @@ -2022,6 +2121,8 @@ TEST_P(InstFloat, FMV_X_D) { EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); + + EXPECT_GROUP(R"(fmv.x.d t0, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_X_W) { @@ -2055,6 +2156,8 @@ TEST_P(InstFloat, FMV_X_W) { EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); + + EXPECT_GROUP(R"(fmv.x.w t0, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_D_X) { @@ -2089,6 +2192,8 @@ TEST_P(InstFloat, FMV_D_X) { EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); + + EXPECT_GROUP(R"(fmv.d.x fa4, t0)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_W_X) { @@ -2123,6 +2228,8 @@ TEST_P(InstFloat, FMV_W_X) { EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); + + EXPECT_GROUP(R"(fmv.w.x fa4, t0)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FEQ_D) { @@ -2156,6 +2263,8 @@ TEST_P(InstFloat, FEQ_D) { EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); + + EXPECT_GROUP(R"(feq.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FEQ_S) { @@ -2213,6 +2322,8 @@ TEST_P(InstFloat, FEQ_S) { EXPECT_EQ(getGeneralRegister(5), 0x1); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(feq.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLT_D) { @@ -2248,6 +2359,8 @@ TEST_P(InstFloat, FLT_D) { EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(29), 1); + + EXPECT_GROUP(R"(flt.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLT_S) { @@ -2307,6 +2420,8 @@ TEST_P(InstFloat, FLT_S) { EXPECT_EQ(getGeneralRegister(5), 0x0); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(flt.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLE_D) { @@ -2342,6 +2457,8 @@ TEST_P(InstFloat, FLE_D) { EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(29), 1); + + EXPECT_GROUP(R"(fle.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLE_S) { @@ -2401,6 +2518,8 @@ TEST_P(InstFloat, FLE_S) { EXPECT_EQ(getGeneralRegister(5), 0x1); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(fle.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMIN_D) { @@ -2444,6 +2563,8 @@ TEST_P(InstFloat, FMIN_D) { EXPECT_EQ(getFPRegister(3), 0x8000000000000000); EXPECT_EQ(getFPRegister(4), (double)-0); EXPECT_EQ(getFPRegister(4), 0x8000000000000000); + + EXPECT_GROUP(R"(fmin.d fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMIN_S) { @@ -2510,6 +2631,8 @@ TEST_P(InstFloat, FMIN_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmin.s fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMAX_D) { @@ -2551,6 +2674,8 @@ TEST_P(InstFloat, FMAX_D) { EXPECT_EQ(getFPRegister(3), (double)0); EXPECT_EQ(getFPRegister(3), 0x0000000000000000); EXPECT_EQ(getFPRegister(4), 0x0000000000000000); + + EXPECT_GROUP(R"(fmax.d fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMAX_S) { @@ -2618,6 +2743,8 @@ TEST_P(InstFloat, FMAX_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmax.s fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, RoundToNearest) { diff --git a/test/regression/riscv/instructions/jump.cc b/test/regression/riscv/instructions/jump.cc index 968e03fd99..5f3c59520b 100644 --- a/test/regression/riscv/instructions/jump.cc +++ b/test/regression/riscv/instructions/jump.cc @@ -3,6 +3,7 @@ namespace { using InstJump = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstJump, jalr) { RUN_RISCV(R"( @@ -19,6 +20,8 @@ TEST_P(InstJump, jalr) { EXPECT_EQ(getGeneralRegister(29), 3); EXPECT_EQ(getGeneralRegister(1), 16); EXPECT_EQ(getGeneralRegister(5), 8); + + EXPECT_GROUP(R"(jalr ra, t1, 4)", BRANCH); } TEST_P(InstJump, jalrAlias) { @@ -31,6 +34,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(31), 3); EXPECT_EQ(getGeneralRegister(1), 8); + EXPECT_GROUP(R"(jalr t0)", BRANCH); + RUN_RISCV(R"( addi ra, ra, 12 ret # jalr zero, ra, 0 @@ -41,6 +46,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(1), 12); EXPECT_EQ(getGeneralRegister(0), 0); + EXPECT_GROUP(R"(ret)", BRANCH); + RUN_RISCV(R"( addi t0, t0, 12 jr t0 # jalr zero, t0, 0 @@ -50,6 +57,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(31), 3); EXPECT_EQ(getGeneralRegister(1), 0); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(jr t0)", BRANCH); } TEST_P(InstJump, jal) { @@ -66,6 +75,8 @@ TEST_P(InstJump, jal) { EXPECT_EQ(getGeneralRegister(29), 3); EXPECT_EQ(getGeneralRegister(1), 12); EXPECT_EQ(getGeneralRegister(5), 4); + + EXPECT_GROUP(R"(jal ra, 12)", BRANCH); } TEST_P(InstJump, jalAlias) { @@ -84,6 +95,9 @@ TEST_P(InstJump, jalAlias) { EXPECT_EQ(getGeneralRegister(5), 0); EXPECT_EQ(getGeneralRegister(1), 20); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(j 12)", BRANCH); + EXPECT_GROUP(R"(jal -12)", BRANCH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstJump, diff --git a/test/regression/riscv/instructions/load.cc b/test/regression/riscv/instructions/load.cc index 9f59fee327..0e2f919cd7 100644 --- a/test/regression/riscv/instructions/load.cc +++ b/test/regression/riscv/instructions/load.cc @@ -3,6 +3,7 @@ namespace { using InstLoad = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstLoad, lb) { initialHeapData_.resize(16); @@ -28,6 +29,8 @@ TEST_P(InstLoad, lb) { EXPECT_EQ(getGeneralRegister(28), 0x0000000000000012); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFAD); + EXPECT_GROUP(R"(lb t2, -2(t5))", LOAD_INT); + // Load byte unsigned RUN_RISCV(R"( li a7, 214 @@ -44,6 +47,8 @@ TEST_P(InstLoad, lb) { EXPECT_EQ(getGeneralRegister(29), 0x0000000000000078); EXPECT_EQ(getGeneralRegister(28), 0x0000000000000012); EXPECT_EQ(getGeneralRegister(7), 0x00000000000000AD); + + EXPECT_GROUP(R"(lbu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, lh) { @@ -70,6 +75,8 @@ TEST_P(InstLoad, lh) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFFFFFED12); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFDEAD); + EXPECT_GROUP(R"(lh t2, -2(t5))", LOAD_INT); + // Load half word unsigned RUN_RISCV(R"( li a7, 214 @@ -86,6 +93,8 @@ TEST_P(InstLoad, lh) { EXPECT_EQ(getGeneralRegister(29), 0x0000000000005678); EXPECT_EQ(getGeneralRegister(28), 0x000000000000ED12); EXPECT_EQ(getGeneralRegister(7), 0x000000000000DEAD); + + EXPECT_GROUP(R"(lhu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, lw) { @@ -112,6 +121,8 @@ TEST_P(InstLoad, lw) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFEBDAED12); EXPECT_EQ(getGeneralRegister(7), 0x000000005678DEAD); + EXPECT_GROUP(R"(lw t2, -2(t5))", LOAD_INT); + RUN_RISCV(R"( li a7, 214 ecall @@ -127,6 +138,8 @@ TEST_P(InstLoad, lw) { EXPECT_EQ(getGeneralRegister(29), 0x0000000012345678); EXPECT_EQ(getGeneralRegister(28), 0x00000000EBDAED12); EXPECT_EQ(getGeneralRegister(7), 0x000000005678DEAD); + + EXPECT_GROUP(R"(lwu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, ld) { @@ -152,6 +165,8 @@ TEST_P(InstLoad, ld) { EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); EXPECT_EQ(getGeneralRegister(28), 0x654321FEEBDAED12); EXPECT_EQ(getGeneralRegister(7), 0xDAED12345678DEAD); + + EXPECT_GROUP(R"(ld t2, -2(t5))", LOAD_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstLoad, diff --git a/test/regression/riscv/instructions/multiplyDivide.cc b/test/regression/riscv/instructions/multiplyDivide.cc index 1016d06517..9894ec485a 100644 --- a/test/regression/riscv/instructions/multiplyDivide.cc +++ b/test/regression/riscv/instructions/multiplyDivide.cc @@ -3,6 +3,7 @@ namespace { using InstMulDiv = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstMulDiv, mul) { initialHeapData_.resize(16); @@ -34,6 +35,8 @@ TEST_P(InstMulDiv, mul) { EXPECT_EQ(getGeneralRegister(18), 0x80000000); EXPECT_EQ(getGeneralRegister(19), 0x8000000000000000); // 2^31 * 2^32 = 2^63 (NO overflow) + + EXPECT_GROUP(R"(mul s3, s2, t2)", INT_MUL); } // TODO NYI, tests should fail @@ -54,6 +57,8 @@ TEST_P(InstMulDiv, mul) { // EXPECT_EQ(getGeneralRegister(31), -1); // EXPECT_EQ(getGeneralRegister(29), 0); // EXPECT_EQ(getGeneralRegister(28), 1); +// +// EXPECT_GROUP(R"()", INT_MUL); //} TEST_P(InstMulDiv, mulhu) { @@ -71,6 +76,8 @@ TEST_P(InstMulDiv, mulhu) { )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFE); + + EXPECT_GROUP(R"(mulhu t4, t6, t6)", INT_MUL); } // TODO NYI, tests should fail @@ -89,6 +96,8 @@ TEST_P(InstMulDiv, mulhu) { // )"); // EXPECT_EQ(getGeneralRegister(31), -1); // EXPECT_EQ(getGeneralRegister(29), -1); +// +// EXPECT_GROUP(R"()", INT_MUL); //} TEST_P(InstMulDiv, mulw) { @@ -106,12 +115,13 @@ TEST_P(InstMulDiv, mulw) { li t4, 6 slli t3, t5, 30 mulw t2, t4, t3 - )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(30), 1); EXPECT_EQ(getGeneralRegister(28), 1 << 30); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFF80000000); + + EXPECT_GROUP(R"(mulw t2, t4, t3)", INT_MUL); } TEST_P(InstMulDiv, div) { @@ -136,7 +146,6 @@ TEST_P(InstMulDiv, div) { div t2, s2, s3 ld t1, 8(a0) div s4, t1, t6 - )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(30), 1); //-1/-1 = 1 @@ -147,6 +156,8 @@ TEST_P(InstMulDiv, div) { EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0x8000000000000000); // division overflow + + EXPECT_GROUP(R"(div s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divw) { @@ -181,6 +192,8 @@ TEST_P(InstMulDiv, divw) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0xFFFFFFFF80000000); // division overflow + + EXPECT_GROUP(R"(divw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divu) { @@ -216,6 +229,8 @@ TEST_P(InstMulDiv, divu) { EXPECT_EQ(getGeneralRegister(7), 8); // 16/2 = 8 EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0); // big / max pos = 0 + + EXPECT_GROUP(R"(divu s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divuw) { @@ -251,6 +266,8 @@ TEST_P(InstMulDiv, divuw) { EXPECT_EQ(getGeneralRegister(7), 8); // 16/2 = 8 EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0); // // big pos / max pos = 0 + + EXPECT_GROUP(R"(divuw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, rem) { @@ -287,6 +304,8 @@ TEST_P(InstMulDiv, rem) { EXPECT_EQ(getGeneralRegister(7), -2); // -16/-7 = -2 EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0); // max pos/-1 = 0 + + EXPECT_GROUP(R"(rem s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remw) { @@ -327,6 +346,8 @@ TEST_P(InstMulDiv, remw) { EXPECT_EQ(getGeneralRegister(7), -2); // -16/-7 = 2 EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0); // big pos/max pos = 0 + + EXPECT_GROUP(R"(remw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remu) { @@ -364,6 +385,8 @@ TEST_P(InstMulDiv, remu) { EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0x8000000000000000); // big pos/max pos = big pos + + EXPECT_GROUP(R"(remu s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remuw) { @@ -405,6 +428,8 @@ TEST_P(InstMulDiv, remuw) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0xFFFFFFFF80000000); // big pos/max pos = 0 + + EXPECT_GROUP(R"(remuw s4, t1, t6)", INT_DIV_OR_SQRT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstMulDiv, diff --git a/test/regression/riscv/instructions/store.cc b/test/regression/riscv/instructions/store.cc index b53a396d88..ea2260481b 100644 --- a/test/regression/riscv/instructions/store.cc +++ b/test/regression/riscv/instructions/store.cc @@ -3,6 +3,7 @@ namespace { using InstStore = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstStore, sb) { initialHeapData_.resize(16); @@ -23,6 +24,8 @@ TEST_P(InstStore, sb) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(33), 0x0012AA56); EXPECT_EQ(getMemoryValue(37), 0x00005400); + + EXPECT_GROUP(R"(sb t6, 6(a0))", STORE_INT); } TEST_P(InstStore, sh) { @@ -49,6 +52,8 @@ TEST_P(InstStore, sh) { EXPECT_EQ(getMemoryValue(64), 0x1200AA78); EXPECT_EQ(getMemoryValue(69), 0x00015400); EXPECT_EQ(getMemoryValue(73), 0x0054AA00); + + EXPECT_GROUP(R"(sh t6, 10(a0))", STORE_INT); } TEST_P(InstStore, sw) { @@ -80,6 +85,8 @@ TEST_P(InstStore, sw) { EXPECT_EQ(getMemoryValue(69), 0x0087015400AAADBE); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x5400AA00); + + EXPECT_GROUP(R"(sw t6, 0(sp))", STORE_INT); } TEST_P(InstStore, sd) { @@ -110,6 +117,8 @@ TEST_P(InstStore, sd) { EXPECT_EQ(getMemoryValue(68), 0x8765000001540000); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 4), 0x000154000000AA01); + + EXPECT_GROUP(R"(sd t6, 4(sp))", STORE_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstStore,