From 19112f237e876346dcf795ccfef623334c004b21 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 19 Jan 2023 16:09:57 +0000 Subject: [PATCH 001/115] Initial CSR implementation. Currently Capstone does not decode CSR addresses correctly so all implementations are left blank --- src/include/simeng/arch/Architecture.hh | 3 +- .../simeng/arch/aarch64/Architecture.hh | 3 +- src/include/simeng/arch/riscv/Architecture.hh | 20 ++++++++++++- src/lib/arch/aarch64/Architecture.cc | 3 +- src/lib/arch/riscv/Architecture.cc | 23 +++++++++++++-- src/lib/arch/riscv/Instruction_decode.cc | 3 ++ src/lib/arch/riscv/Instruction_execute.cc | 28 +++++++++++++++++++ src/lib/models/emulation/Core.cc | 2 +- src/lib/models/inorder/Core.cc | 3 +- src/lib/models/outoforder/Core.cc | 3 +- test/regression/riscv/CMakeLists.txt | 1 + test/regression/riscv/instructions/csr.cc | 18 ++++++++++++ 12 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 test/regression/riscv/instructions/csr.cc diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 4dbe377587..6758f9adfe 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -108,7 +108,8 @@ class Architecture { /** Updates System registers of any system-based timers. */ virtual void updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations) const = 0; + const uint64_t iterations, + const uint64_t retired) const = 0; }; } // namespace arch diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 39d399dc7d..cbd5046c43 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -60,7 +60,8 @@ class Architecture : public arch::Architecture { /** Updates System registers of any system-based timers. */ void updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations) const override; + const uint64_t iterations, + const uint64_t retired) const override; /** Returns the physical register structure as defined within the config file */ diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 9e8c169f7a..e2b3af3e6c 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -14,6 +14,17 @@ namespace simeng { namespace arch { namespace riscv { +typedef enum riscv_sysreg { + RISCV_SYSREG_FFLAGS = 0x001, + RISCV_SYSREG_FRM = 0x002, + RISCV_SYSREG_FCSR = 0x003, + + RISCV_SYSREG_CYCLE = 0xC00, + RISCV_SYSREG_TIME = 0xC01, + RISCV_SYSREG_INSTRET = 0xC02, + +} riscv_sysreg; + /* A basic RISC-V implementation of the `Architecture` interface. */ class Architecture : public arch::Architecture { public: @@ -51,7 +62,8 @@ class Architecture : public arch::Architecture { /** Updates System registers of any system-based timers. */ void updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations) const override; + const uint64_t iterations, + const uint64_t retired) const override; /** Returns the physical register structure as defined within the config file */ @@ -95,6 +107,12 @@ class Architecture : public arch::Architecture { /** A reference to a Linux kernel object to forward syscalls to. */ kernel::Linux& linux_; + + /** System Register of Processor Cycle Counter. */ + simeng::Register cycleSystemReg_; + + /** System Register of Processor Retired Counter. */ + simeng::Register retiredSystemReg_; }; } // namespace riscv diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 08b807eb97..b5ed164678 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -286,7 +286,8 @@ uint64_t Architecture::getVectorLength() const { return VL_; } uint64_t Architecture::getStreamingVectorLength() const { return SVL_; } void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations) const { + const uint64_t iterations, + const uint64_t retired) const { // Update the Processor Cycle Counter to total cycles completed. regFile->set(PCCreg_, iterations); // Update Virtual Counter Timer at correct frequency. diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 5d18349dc5..9f408d27fc 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -26,6 +26,23 @@ Architecture::Architecture(kernel::Linux& kernel, YAML::Node config) cs_option(capstoneHandle, CS_OPT_DETAIL, CS_OPT_ON); + // Generate zero-indexed system register map + systemRegisterMap_[RISCV_SYSREG_FFLAGS] = systemRegisterMap_.size(); + systemRegisterMap_[RISCV_SYSREG_FRM] = systemRegisterMap_.size(); + systemRegisterMap_[RISCV_SYSREG_FCSR] = systemRegisterMap_.size(); + + systemRegisterMap_[RISCV_SYSREG_CYCLE] = systemRegisterMap_.size(); + systemRegisterMap_[RISCV_SYSREG_TIME] = systemRegisterMap_.size(); + systemRegisterMap_[RISCV_SYSREG_INSTRET] = systemRegisterMap_.size(); + + cycleSystemReg_ = { + RegisterType::SYSTEM, + static_cast(getSystemRegisterTag(RISCV_SYSREG_CYCLE))}; + + retiredSystemReg_ = { + RegisterType::SYSTEM, + static_cast(getSystemRegisterTag(RISCV_SYSREG_INSTRET))}; + // Instantiate an executionInfo entry for each group in the InstructionGroup // namespace. for (int i = 0; i < NUM_GROUPS; i++) { @@ -262,9 +279,11 @@ uint16_t Architecture::getNumSystemRegisters() const { return static_cast(systemRegisterMap_.size()); } -// Left blank as no implementation necessary void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations) const { + const uint64_t iterations, + const uint64_t retired) const { + regFile->set(cycleSystemReg_, iterations); + regFile->set(retiredSystemReg_, retired); } } // namespace riscv diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 6db263796b..ab0aa735ea 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -59,6 +59,9 @@ void Instruction::invalidateIfNotImplemented() { metadata.opcode <= Opcode::RISCV_XORI) return; if (metadata.opcode == Opcode::RISCV_FENCE) return; + if (metadata.opcode >= Opcode::RISCV_CSRRC && + metadata.opcode <= Opcode::RISCV_CSRRWI) + return; exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 005982a9fc..f4dea48f94 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -1,5 +1,6 @@ #include +#include #include #include "InstructionMetadata.hh" @@ -827,6 +828,33 @@ void Instruction::execute() { break; } + // Control and Status Register extension (Zicsr) + // Do not read-modify-write ATOMICALLY + case Opcode::RISCV_CSRRW: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRWI: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRS: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRSI: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRC: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRCI: { + executionNYI(); + break; + } + default: return executionNYI(); } diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 1d572ee160..934c859202 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -159,7 +159,7 @@ void Core::tick() { } execute(uop); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, ticks_); } void Core::execute(std::shared_ptr& uop) { diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index a9604bc085..834b8a733f 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -107,7 +107,8 @@ void Core::tick() { } fetchUnit_.requestFromPC(); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, + writebackUnit_.getInstructionsWrittenCount()); } bool Core::hasHalted() const { diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index df2237cfe8..3dd86a7ad2 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -163,7 +163,8 @@ void Core::tick() { flushIfNeeded(); fetchUnit_.requestFromPC(); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, + writebackUnit_.getInstructionsWrittenCount()); } void Core::flushIfNeeded() { diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index 1821d7ab5f..71bc607a93 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(regression-riscv instructions/jump.cc instructions/branch.cc instructions/atomic.cc + instructions/csr.cc ) target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc new file mode 100644 index 0000000000..94c0d76f6b --- /dev/null +++ b/test/regression/riscv/instructions/csr.cc @@ -0,0 +1,18 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using InstCsr = RISCVRegressionTest; + +TEST_P(InstCsr, jalr) { + RUN_RISCV(R"( + csrrw t1, cycle, t1 + )"); +} + +INSTANTIATE_TEST_SUITE_P(RISCV, InstCsr, + ::testing::Values(std::make_tuple(EMULATION, + YAML::Load("{}"))), + paramToString); + +} // namespace From 5facccf3583bf10053682e586f59fec96a7e4f1d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 19 Jan 2023 16:17:40 +0000 Subject: [PATCH 002/115] Update mock architecture updateSystemTimerRegisters method --- test/unit/MockArchitecture.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index e324ced9ac..c6e9bc12e6 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -26,8 +26,9 @@ class MockArchitecture : public arch::Architecture { std::vector(YAML::Node config)); MOCK_CONST_METHOD1(getConfigPhysicalRegisterQuantities, std::vector(YAML::Node config)); - MOCK_CONST_METHOD2(updateSystemTimerRegisters, - void(RegisterFileSet* regFile, const uint64_t iterations)); + MOCK_CONST_METHOD3(updateSystemTimerRegisters, + void(RegisterFileSet* regFile, const uint64_t iterations, + const uint64_t retired)); }; } // namespace simeng From 070f71c4f6f479891edab8cc894b6261b0547c3c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 19 Jan 2023 16:47:41 +0000 Subject: [PATCH 003/115] Take changes from riscv-F-extension branch and delete it --- src/lib/arch/riscv/Instruction_address.cc | 6 +- src/lib/arch/riscv/Instruction_decode.cc | 23 +++++ src/lib/arch/riscv/Instruction_execute.cc | 21 +++++ test/regression/riscv/CMakeLists.txt | 3 +- test/regression/riscv/RISCVRegressionTest.hh | 6 ++ test/regression/riscv/instructions/float.cc | 95 ++++++++++++++++++++ 6 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 test/regression/riscv/instructions/float.cc diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index e893ce3644..b779703af0 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -39,7 +39,11 @@ span Instruction::generateAddresses() { switch (metadata.opcode) { case Opcode::RISCV_SD: [[fallthrough]]; - case Opcode::RISCV_LD: { + case Opcode::RISCV_LD: + [[fallthrough]]; + case Opcode::RISCV_FSD: + [[fallthrough]]; + case Opcode::RISCV_FLD: { setMemoryAddresses({{address, 8}}); break; } diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index ab0aa735ea..43f6d19621 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -19,6 +19,22 @@ namespace riscv { Register csRegToRegister(unsigned int reg) { // Check from top of the range downwards + // Modulus ensures only 64 bit registers are recognised + if (RISCV_REG_F31_64 >= reg && reg >= RISCV_REG_F0_64 && reg % 2 == 0) { + // Register ft0.64 has encoding 34 with subsequent encodings interleaved + // with 32 bit floating point registers. See riscv.h + return {RegisterType::FLOAT, static_cast((reg - 34) / 2)}; + } + + // Only supporting 64 bit floating point registers for now. Commented out to + // trip assertion + // // Modulus ensures only 32 bit registers are recognised + // if (RISCV_REG_F31_32 >= reg && reg >= RISCV_REG_F0_32 && reg % 2 == 1) { + // // Register ft0.32 has encoding 33 with subsequent encodings interleaved + // // with 64 bit floating point registers. See riscv.h + // return {RegisterType::FLOAT, static_cast((reg - 33) / 2)}; + // } + if (RISCV_REG_X31 >= reg && reg >= RISCV_REG_X1) { // Capstone produces 1 indexed register operands return {RegisterType::GENERAL, static_cast(reg - 1)}; @@ -62,6 +78,9 @@ void Instruction::invalidateIfNotImplemented() { if (metadata.opcode >= Opcode::RISCV_CSRRC && metadata.opcode <= Opcode::RISCV_CSRRWI) return; + if (metadata.opcode == Opcode::RISCV_FADD_D) return; + if (metadata.opcode == Opcode::RISCV_FSD) return; + if (metadata.opcode == Opcode::RISCV_FLD) return; exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; @@ -110,6 +129,8 @@ void Instruction::decode() { case Opcode::RISCV_LW: case Opcode::RISCV_LWU: case Opcode::RISCV_LD: + case Opcode::RISCV_FLW: + case Opcode::RISCV_FLD: isLoad_ = true; break; case Opcode::RISCV_SC_D: @@ -126,6 +147,8 @@ void Instruction::decode() { case Opcode::RISCV_SW: case Opcode::RISCV_SH: case Opcode::RISCV_SD: + case Opcode::RISCV_FSW: + case Opcode::RISCV_FSD: isStore_ = true; break; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index f4dea48f94..93ba6099f0 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -830,6 +830,8 @@ void Instruction::execute() { // Control and Status Register extension (Zicsr) // Do not read-modify-write ATOMICALLY + // Left unimplemented due to Capstone being unable to disassemble CSR + // addresses case Opcode::RISCV_CSRRW: { executionNYI(); break; @@ -855,6 +857,25 @@ void Instruction::execute() { break; } + // Single-Precision Floating-Point (F) + // Double-Precision Floating-Point (D) + case Opcode::RISCV_FADD_D: { // FADD.D rd,rs1,rs2 + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(rs1 + rs2, 8); + break; + } + case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm + memoryData[0] = operands[0]; + break; + } + case Opcode::RISCV_FLD: { // FLD rd,rs1,imm + // Note: elements of memory data are RegisterValue's + results[0] = memoryData[0].get(); + break; + } + default: return executionNYI(); } diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index 71bc607a93..e62dfd52a8 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -12,7 +12,8 @@ add_executable(regression-riscv instructions/branch.cc instructions/atomic.cc instructions/csr.cc - ) + instructions/float.cc + ) target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(regression-riscv regression-test-base) diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 29ce769783..f8e6fbf387 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -80,6 +80,12 @@ class RISCVRegressionTest : public RegressionTest { return getRegister({simeng::arch::riscv::RegisterType::GENERAL, tag}); } + /** Get the value of a floating point purpose register. */ + template + T getFPRegister(uint8_t tag) const { + return getRegister({simeng::arch::riscv::RegisterType::FLOAT, tag}); + } + /** Create a port allocator for an out-of-order core model. */ virtual std::unique_ptr createPortAllocator() const override; diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc new file mode 100644 index 0000000000..074531c9f8 --- /dev/null +++ b/test/regression/riscv/instructions/float.cc @@ -0,0 +1,95 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using InstFloat = RISCVRegressionTest; + +TEST_P(InstFloat, FLD) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + fld ft0, 0(a0) + fld ft1, 8(a0) + fld ft2, 16(a0) + fld ft3, 24(a0) + )"); + + EXPECT_EQ(getFPRegister(0), 1.0); + EXPECT_EQ(getFPRegister(1), 123.456); + EXPECT_EQ(getFPRegister(2), -0.00032); + EXPECT_EQ(getFPRegister(3), 123456); +} + +TEST_P(InstFloat, FSD) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + fld ft0, 0(a0) + fld ft1, 8(a0) + fld ft2, 16(a0) + fld ft3, 24(a0) + fsd ft3, 0(a0) + fsd ft2, 8(a0) + fsd ft1, 16(a0) + fsd ft0, 24(a0) + )"); + + EXPECT_EQ(getFPRegister(0), 1.0); + EXPECT_EQ(getFPRegister(1), 123.456); + EXPECT_EQ(getFPRegister(2), -0.00032); + EXPECT_EQ(getFPRegister(3), 123456); + + EXPECT_EQ(getGeneralRegister(10), 64); + + EXPECT_EQ(getMemoryValue(64), 123456); + EXPECT_EQ(getMemoryValue(72), -0.00032); + EXPECT_EQ(getMemoryValue(80), 123.456); + EXPECT_EQ(getMemoryValue(88), 1.0); +} + +TEST_P(InstFloat, FADD_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + fld ft0, 0(a0) + fld ft1, 8(a0) + fld ft2, 16(a0) + fld ft3, 24(a0) + fadd.d ft4, ft0, ft1 + fadd.d ft5, ft1, ft2 + )"); + + EXPECT_EQ(getFPRegister(4), 124.456); + EXPECT_EQ(getFPRegister(5), 123.456 - 0.00032); +} + +INSTANTIATE_TEST_SUITE_P(RISCV, InstFloat, + ::testing::Values(std::make_tuple(EMULATION, + YAML::Load("{}"))), + paramToString); + +} // namespace \ No newline at end of file From 7800310c9f3241fee0e585d33355e4f01e2f4689 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 16 Feb 2023 16:08:29 +0000 Subject: [PATCH 004/115] Majority of F extension support --- configs/DEMO_RISCV.yaml | 4 +- src/include/simeng/arch/riscv/Instruction.hh | 5 +- src/include/simeng/kernel/Linux.hh | 4 + src/lib/arch/riscv/ExceptionHandler.cc | 26 + src/lib/arch/riscv/InstructionMetadata.cc | 148 ++ src/lib/arch/riscv/Instruction_address.cc | 6 +- src/lib/arch/riscv/Instruction_decode.cc | 65 +- src/lib/arch/riscv/Instruction_execute.cc | 552 +++++- src/lib/kernel/Linux.cc | 45 + src/lib/models/emulation/Core.cc | 2 +- test/regression/riscv/instructions/float.cc | 1593 +++++++++++++++++- 11 files changed, 2392 insertions(+), 58 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index e5a11d3c54..381b6fd70e 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -5,7 +5,7 @@ Core: ISA: rv64 - Simulation-Mode: outoforder + Simulation-Mode: emulation Clock-Frequency: 2.5 Fetch-Block-Size: 32 Fetch: @@ -36,7 +36,7 @@ Branch-Predictor: Branch-Predictor: BTB-bitlength: 16 L1-Data-Memory: - Interface-Type: Fixed + Interface-Type: Flat L1-Instruction-Memory: Interface-Type: Flat LSQ-L1-Interface: diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 61b83037ca..cb401c4399 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -163,10 +163,13 @@ class Instruction : public simeng::Instruction { * automatically supplied as zero. */ static const Register ZERO_REGISTER; + /** Canonical 64-bit NaN defined by IEEE 754*/ + static const uint64_t UPPER_32_ALL_1 = 0xFFFFFFFF00000000; + private: /** The maximum number of source registers any supported RISC-V instruction * can have. */ - static const uint8_t MAX_SOURCE_REGISTERS = 2; + static const uint8_t MAX_SOURCE_REGISTERS = 3; /** The maximum number of destination registers any supported RISC-V * instruction can have. */ static const uint8_t MAX_DESTINATION_REGISTERS = 1; diff --git a/src/include/simeng/kernel/Linux.hh b/src/include/simeng/kernel/Linux.hh index 0908d59006..5292ecd03d 100644 --- a/src/include/simeng/kernel/Linux.hh +++ b/src/include/simeng/kernel/Linux.hh @@ -196,6 +196,10 @@ class Linux { /** munmap syscall: deletes the mappings for the specified address range. */ int64_t munmap(uint64_t addr, size_t length); + /** mremap syscall: expand memory mapping */ + uint64_t mremap(uint64_t oid_address, size_t old_size, size_t new_size, + int flags, uint64_t new_address); + /** mmap syscall: map files or devices into memory. */ uint64_t mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset); diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index 8f76c4cc3a..b68a0cf410 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -565,6 +565,32 @@ bool ExceptionHandler::init() { stateChange = {ChangeType::REPLACEMENT, {R0}, {result}}; break; } + case 216: { // mremap + uint64_t old_address = registerFileSet.get(R0).get(); + size_t old_size = registerFileSet.get(R1).get(); + size_t new_size = registerFileSet.get(R2).get(); + int flags = registerFileSet.get(R3).get(); + uint64_t new_address = registerFileSet.get(R4).get(); + + // Currently only MAYMOVE supported + if (flags == 1) { + uint64_t result = linux_.mremap(old_address, old_size, new_size, + flags, new_address); + if (result == -1) { + stateChange = { + ChangeType::REPLACEMENT, {R0}, {static_cast(-1)}}; + } else { + stateChange = {ChangeType::REPLACEMENT, {R0}, {result}}; + } + } else { + printException(instruction_); + std::cout << "Unsupported arguments for syscall: " << syscallId + << std::endl; + return fatal(); + } + + break; + } case 222: { // mmap uint64_t addr = registerFileSet.get(R0).get(); size_t length = registerFileSet.get(R1).get(); diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 595f5f6ece..f7fc991811 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -4,6 +4,8 @@ #include #include +#include "simeng/arch/riscv/Architecture.hh" + namespace simeng { namespace arch { namespace riscv { @@ -252,6 +254,152 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { } break; } + + case Opcode::RISCV_CSRRS: { + if (operandCount == 1 && strcmp(mnemonic, "frflags") == 0) { + // frflags Rs is pseudo of CSRRS Rs, fflags, zero (Read FP exception + // flags) CSRRS Rs, _, _ -> CSRRS Rs, fflags, zero + operands[1].type = + RISCV_OP_IMM; // TODO needs to become reg when CS updated + operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + + operands[2].type = RISCV_OP_REG; + operands[2].reg = 1; + + operandCount = 3; + } else if (strcmp(mnemonic, "rdinstret") == 0) { + assert(false && "Unimplemented psuedoinstruction rdinstret"); + } else if (strcmp(mnemonic, "rdcycle") == 0) { + assert(false && "Unimplemented psuedoinstruction rdcycle"); + } else if (strcmp(mnemonic, "rdtime") == 0) { + assert(false && "Unimplemented psuedoinstruction rdtime"); + } else if (strcmp(mnemonic, "csrr") == 0) { + assert(false && "Unimplemented psuedoinstruction csrr"); + } else if (strcmp(mnemonic, "csrs") == 0) { + assert(false && "Unimplemented psuedoinstruction csrs"); + } else if (strcmp(mnemonic, "frcsr") == 0) { + assert(false && "Unimplemented psuedoinstruction rdtime"); + } else if (operandCount == 1 && strcmp(mnemonic, "frrm") == 0) { + // frrm Rs is pseudo of CSRRS Rs, frm, zero (Read FP rounding mode) + // CSRRS Rs, _, _ -> CSRRS Rs, frm, zero + operands[1].type = + RISCV_OP_IMM; // TODO needs to become reg when CS updated + operands[1].reg = RISCV_SYSREG_FRM; // frm address + + operands[2].type = RISCV_OP_REG; + operands[2].reg = 1; + + operandCount = 3; + } + break; + } + case Opcode::RISCV_CSRRW: { + if (operandCount == 1 && strcmp(mnemonic, "fsflags") == 0) { + // fsflags Rs is pseudo of CSRRW zero, fflags, rs (Write FP exception + // flags) + // CSRRW Rs, _, _ -> CSRRW zero, fflags, Rs + operands[2] = operands[0]; + + operands[0].type = RISCV_OP_REG; + operands[0].reg = 1; + + operands[1].type = + RISCV_OP_IMM; // TODO needs to become reg when CS updated + operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + + operandCount = 3; + } else if (strcmp(mnemonic, "csrw") == 0) { + assert(false && "Unimplemented psuedoinstruction csrw"); + } else if (strcmp(mnemonic, "fscsr") == 0) { + assert(false && "Unimplemented psuedoinstruction fscsr"); + } else if (strcmp(mnemonic, "fscsr") == 0) { + // 2 pseudoinstructions with same name but different number of registers + assert(false && "Unimplemented psuedoinstruction fscsr"); + } else if (operandCount == 1 && strcmp(mnemonic, "fsrm") == 0) { + // fsrm Rs is pseudo of CSRRW zero, frm, rs (Write FP rounding mode) + // CSRRW Rs, _, _ -> CSRRW zero, frm, Rs + operands[2] = operands[0]; + + operands[0].type = RISCV_OP_REG; + operands[0].reg = 1; + + operands[1].type = + RISCV_OP_IMM; // TODO needs to become reg when CS updated + operands[1].reg = RISCV_SYSREG_FRM; // frm address + + operandCount = 3; + } else if (strcmp(mnemonic, "fsrm") == 0) { + assert(false && "Unimplemented psuedoinstruction fsrm"); + } else if (strcmp(mnemonic, "fsflags") == 0) { + assert(false && "Unimplemented psuedoinstruction fsflags"); + } else if (strcmp(mnemonic, "fsflags") == 0) { + assert(false && "Unimplemented psuedoinstruction fsflags"); + } + break; + } + + case Opcode::RISCV_FSGNJ_S: { + if (operandCount == 2 && strcmp(mnemonic, "fmv.s") == 0) { + // fmv.s rd, rs is pseudo of fsgnj.s rd, rs, rs (Copy single-precision + // register) + // fsgnj.s Rd, Rs, _ -> fsgnj.s Rd, Rs, Rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } + case Opcode::RISCV_FSGNJX_S: { + if (operandCount == 2 && strcmp(mnemonic, "fabs.s") == 0) { + // fabs.s rd, rs is pseudo of fsgnjx.s rd, rs, rs (Single-precision + // absolute value) + // fsgnjx.s rd, rs, _ -> fsgnjx.s rd, rs, rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } + case Opcode::RISCV_FSGNJN_S: { + if (operandCount == 2 && strcmp(mnemonic, "fneg.s") == 0) { + // fneg.s rd, rs is pseudo of fsgnjn.s rd, rs, rs (Single-precision + // negate) + // fsgnjn.s rd, rs, _ -> fsgnjn.s rd, rs, rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } + + case Opcode::RISCV_FSGNJ_D: { + if (operandCount == 2 && strcmp(mnemonic, "fmv.d") == 0) { + // fmv.d rd, rs is pseudo of fsgnj.d rd, rs, rs (Copy double-precision + // register) + // fsgnj.d Rd, Rs, _ -> fsgnj.d Rd, Rs, Rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } + case Opcode::RISCV_FSGNJX_D: { + if (operandCount == 2 && strcmp(mnemonic, "fabs.d") == 0) { + // fabs.d rd, rs is pseudo of fsgnjx.d rd, rs, rs (Double-precision + // absolute value) + // fsgnjx.d rd, rs, _ -> fsgnjx.d rd, rs, rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } + case Opcode::RISCV_FSGNJN_D: { + // fneg.d rd, rs, fsgnjn.d rd, rs, rs, Double-precision negate + if (operandCount == 2 && strcmp(mnemonic, "fneg.d") == 0) { + // fneg.d rd, rs is pseudo of fsgnjn.d rd, rs, rs (Double-precision + // neagte) + // fsgnjn.d rd, rs, _ -> fsgnjn.d rd, rs, rs + operands[2] = operands[1]; + operandCount = 3; + } + break; + } } } diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index b779703af0..7000645bd6 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -51,7 +51,11 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::RISCV_LW: [[fallthrough]]; - case Opcode::RISCV_LWU: { + case Opcode::RISCV_LWU: + [[fallthrough]]; + case Opcode::RISCV_FSW: + [[fallthrough]]; + case Opcode::RISCV_FLW: { setMemoryAddresses({{address, 4}}); break; } diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 43f6d19621..64ad5156ec 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -19,6 +19,10 @@ namespace riscv { Register csRegToRegister(unsigned int reg) { // Check from top of the range downwards + // Metadata could produce either 64-bit floating point register or 32-bit + // floating point register. Map both encodings to the same SimEng register. + // Only 64-bit registers are supported + // Modulus ensures only 64 bit registers are recognised if (RISCV_REG_F31_64 >= reg && reg >= RISCV_REG_F0_64 && reg % 2 == 0) { // Register ft0.64 has encoding 34 with subsequent encodings interleaved @@ -26,14 +30,12 @@ Register csRegToRegister(unsigned int reg) { return {RegisterType::FLOAT, static_cast((reg - 34) / 2)}; } - // Only supporting 64 bit floating point registers for now. Commented out to - // trip assertion - // // Modulus ensures only 32 bit registers are recognised - // if (RISCV_REG_F31_32 >= reg && reg >= RISCV_REG_F0_32 && reg % 2 == 1) { - // // Register ft0.32 has encoding 33 with subsequent encodings interleaved - // // with 64 bit floating point registers. See riscv.h - // return {RegisterType::FLOAT, static_cast((reg - 33) / 2)}; - // } + // Modulus ensures only 32 bit registers are recognised + if (RISCV_REG_F31_32 >= reg && reg >= RISCV_REG_F0_32 && reg % 2 == 1) { + // Register ft0.32 has encoding 33 with subsequent encodings interleaved + // with 64 bit floating point registers. See riscv.h + return {RegisterType::FLOAT, static_cast((reg - 33) / 2)}; + } if (RISCV_REG_X31 >= reg && reg >= RISCV_REG_X1) { // Capstone produces 1 indexed register operands @@ -79,8 +81,55 @@ void Instruction::invalidateIfNotImplemented() { metadata.opcode <= Opcode::RISCV_CSRRWI) return; if (metadata.opcode == Opcode::RISCV_FADD_D) return; + if (metadata.opcode == Opcode::RISCV_FADD_S) return; if (metadata.opcode == Opcode::RISCV_FSD) return; + if (metadata.opcode == Opcode::RISCV_FSW) return; if (metadata.opcode == Opcode::RISCV_FLD) return; + if (metadata.opcode == Opcode::RISCV_FLW) return; + if (metadata.opcode == Opcode::RISCV_FSUB_D) return; + if (metadata.opcode == Opcode::RISCV_FSUB_S) return; + if (metadata.opcode == Opcode::RISCV_FDIV_D) return; + if (metadata.opcode == Opcode::RISCV_FDIV_S) return; + if (metadata.opcode == Opcode::RISCV_FMUL_D) return; + if (metadata.opcode == Opcode::RISCV_FMUL_S) return; + if (metadata.opcode == Opcode::RISCV_FSQRT_D) return; + if (metadata.opcode == Opcode::RISCV_FSQRT_S) return; + if (metadata.opcode == Opcode::RISCV_FMIN_D) return; + if (metadata.opcode == Opcode::RISCV_FMIN_S) return; + if (metadata.opcode == Opcode::RISCV_FMAX_D) return; + if (metadata.opcode == Opcode::RISCV_FMAX_S) return; + if (metadata.opcode == Opcode::RISCV_FMADD_D) return; + if (metadata.opcode == Opcode::RISCV_FMADD_S) return; + // // if (metadata.opcode == Opcode::RISCV_FMSUB_D) return; + if (metadata.opcode == Opcode::RISCV_FNMSUB_D) return; + if (metadata.opcode == Opcode::RISCV_FNMSUB_S) return; + if (metadata.opcode == Opcode::RISCV_FMSUB_S) return; + if (metadata.opcode == Opcode::RISCV_FCVT_D_L) return; + if (metadata.opcode == Opcode::RISCV_FCVT_D_W) return; + if (metadata.opcode == Opcode::RISCV_FCVT_S_W) return; + if (metadata.opcode == Opcode::RISCV_FCVT_W_D) return; + if (metadata.opcode == Opcode::RISCV_FCVT_W_S) return; + if (metadata.opcode == Opcode::RISCV_FCVT_D_S) return; + if (metadata.opcode == Opcode::RISCV_FCVT_S_D) return; + if (metadata.opcode == Opcode::RISCV_FSGNJ_D) return; + if (metadata.opcode == Opcode::RISCV_FSGNJ_S) return; + if (metadata.opcode == Opcode::RISCV_FSGNJN_S) return; + if (metadata.opcode == Opcode::RISCV_FSGNJN_D) return; + if (metadata.opcode == Opcode::RISCV_FSGNJX_D) return; + if (metadata.opcode == Opcode::RISCV_FSGNJX_S) return; + if (metadata.opcode == Opcode::RISCV_FMV_X_D) return; + if (metadata.opcode == Opcode::RISCV_FMV_X_W) return; + if (metadata.opcode == Opcode::RISCV_FMV_D_X) return; + if (metadata.opcode == Opcode::RISCV_FMV_W_X) return; + if (metadata.opcode == Opcode::RISCV_FEQ_D) return; + if (metadata.opcode == Opcode::RISCV_FEQ_S) return; + if (metadata.opcode == Opcode::RISCV_FLT_D) return; + if (metadata.opcode == Opcode::RISCV_FLT_S) return; + if (metadata.opcode == Opcode::RISCV_FLE_D) return; + if (metadata.opcode == Opcode::RISCV_FLE_S) return; + + std::cout << "[SimEng:RISCV:Decode] Insn: " << metadata.mnemonic << " " + << metadata.operandStr << std::endl; exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 93ba6099f0..c8425b6e5c 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -1,4 +1,5 @@ +#include #include #include #include @@ -10,6 +11,21 @@ namespace simeng { namespace arch { namespace riscv { +/** NaN box single precision floating point values as defined in + * riscv-spec-20191213 page 73 */ +uint64_t NanBox(uint32_t floatAsUint) { + return Instruction::UPPER_32_ALL_1 | static_cast(floatAsUint); +} + +uint64_t NanBoxFloat(float f) { + // TODO there must be a better way + float* fp = (float*)malloc(sizeof(float)); + *fp = f; + uint64_t boxed = NanBox(*reinterpret_cast(fp)); + free(fp); + return boxed; +} + /** Multiply unsigned `a` and unsigned `b`, and return the high 64 bits of the * result. https://stackoverflow.com/a/28904636 */ uint64_t mulhiuu(uint64_t a, uint64_t b) { @@ -75,7 +91,10 @@ void Instruction::execute() { canExecute() && "Attempted to execute an instruction before all operands were provided"); - // Implementation of rv64iam according to the v. 20191213 unprivileged spec + // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec + + // std::cerr << "insn: " << metadata.mnemonic << " " << metadata.operandStr + // << std::endl; executed_ = true; switch (metadata.opcode) { @@ -829,36 +848,106 @@ void Instruction::execute() { } // Control and Status Register extension (Zicsr) - // Do not read-modify-write ATOMICALLY - // Left unimplemented due to Capstone being unable to disassemble CSR - // addresses + // Do not read-modify-write ATOMICALLY + // Left unimplemented due to Capstone being unable to disassemble CSR + // addresses case Opcode::RISCV_CSRRW: { - executionNYI(); + // Do nothing to allow progression + + if (metadata.operands[1].reg == 2) { + // TODO this won't work properly in OoO core as rounding mode could be + // updated before instructions earlier in program order execute causing + // them to be rounded incorrectly + // frm + std::cerr << "CSRRW: " << metadata.mnemonic << " " + << metadata.operandStr + << ", rs1 = " << operands[0].get() + << " , rs2 = " << metadata.operands[1].reg << std::endl; + switch (operands[0].get()) { + case 0: + fesetround(FE_TONEAREST); + break; + case 1: + fesetround(FE_TOWARDZERO); + break; + case 2: + fesetround(FE_DOWNWARD); + break; + case 3: + fesetround(FE_UPWARD); + break; + case 4: + fesetround(FE_TONEAREST); + break; + default: + // Invalid Case + // TODO any subsequent attempt to execute a floating-point operation + // with a dynamic rounding mode will raise an illegal instruction + // exception. + std::cerr << "Invalid rounding mode" << std::endl; + break; + } + } else { + // std::cerr << "Unknown system register" << std::endl; + } break; } - case Opcode::RISCV_CSRRWI: { - executionNYI(); + // // case Opcode::RISCV_CSRRWI: { + // // executionNYI(); + // // break; + // // } + case Opcode::RISCV_CSRRS: { + // dummy implementation only used by floating point frflags, needs + // capstone update to recognise system registers. No update of system + // register as rs1 == zero + + results[0] = RegisterValue(static_cast(0), 8); break; } - case Opcode::RISCV_CSRRS: { - executionNYI(); + // case Opcode::RISCV_CSRRSI: { + // executionNYI(); + // break; + // } + // case Opcode::RISCV_CSRRC: { + // executionNYI(); + // break; + // } + // case Opcode::RISCV_CSRRCI: { + // executionNYI(); + // break; + // } + + // TODO Apart from transfer operations described in the previous + // paragraph, all other floating-point operations on narrower n-bit + // operations, n < FLEN, check if the input operands are correctly + // NaN-boxed, i.e., all upper FLEN−n bits are 1. If so, the n + // least-significant bits of the input are used as the input value, + // otherwise the input value is treated as an n-bit canonical NaN. + + // Single-Precision Floating-Point (F) + // Double-Precision Floating-Point (D) + case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm + memoryData[0] = operands[0]; break; } - case Opcode::RISCV_CSRRSI: { - executionNYI(); + case Opcode::RISCV_FSW: { // FSW rs1,rs2,imm + memoryData[0] = operands[0]; break; } - case Opcode::RISCV_CSRRC: { - executionNYI(); + case Opcode::RISCV_FLD: { // FLD rd,rs1,imm + // Note: elements of memory data are RegisterValue's + results[0] = memoryData[0].get(); break; } - case Opcode::RISCV_CSRRCI: { - executionNYI(); + case Opcode::RISCV_FLW: { // FLW rd,rs1,imm + // Note: elements of memory data are RegisterValue's + // Get as uint32 to allow for NaN boxing + const uint32_t memSingle = memoryData[0].get(); + + results[0] = RegisterValue(NanBox(memSingle), 8); break; } - // Single-Precision Floating-Point (F) - // Double-Precision Floating-Point (D) case Opcode::RISCV_FADD_D: { // FADD.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -866,13 +955,432 @@ void Instruction::execute() { results[0] = RegisterValue(rs1 + rs2, 8); break; } - case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm - memoryData[0] = operands[0]; + case Opcode::RISCV_FADD_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(NanBoxFloat(rs1 + rs2), 8); break; } - case Opcode::RISCV_FLD: { // FLD rd,rs1,imm - // Note: elements of memory data are RegisterValue's - results[0] = memoryData[0].get(); + case Opcode::RISCV_FSUB_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(rs1 - rs2, 8); + break; + } + case Opcode::RISCV_FSUB_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(NanBoxFloat(rs1 - rs2), 8); + break; + } + case Opcode::RISCV_FDIV_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(rs1 / rs2, 8); + break; + } + case Opcode::RISCV_FDIV_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(NanBoxFloat(rs1 / rs2), 8); + break; + } + + case Opcode::RISCV_FMUL_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(rs1 * rs2, 8); + break; + } + case Opcode::RISCV_FMUL_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(NanBoxFloat(rs1 * rs2), 8); + break; + } + + case Opcode::RISCV_FSQRT_D: { + const double rs1 = operands[0].get(); + + const double sqrtAns = sqrt(rs1); + + // With -ve rs1, sqrt = -NaN, but qemu returns canonical (+)NaN. Adjust + // for this here + const double res = std::isnan(sqrtAns) ? nanf("0") : sqrtAns; + + results[0] = RegisterValue(res, 8); + break; + } + case Opcode::RISCV_FSQRT_S: { + const float rs1 = operands[0].get(); + + const float sqrtAns = sqrtf(rs1); + + // With -ve rs1, sqrt = -NaN, but qemu returns canonical (+)NaN. Adjust + // for this here + const float res = std::isnan(sqrtAns) ? nanf("0") : sqrtAns; + + results[0] = RegisterValue(NanBoxFloat(res), 8); + break; + } + + case Opcode::RISCV_FMIN_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + // cpp fmin reference: This function is not required to be sensitive to + // the sign of zero, although some implementations additionally enforce + // that if one argument is +0 and the other is -0, then +0 is returned. + // But RISC-V spec requires this to be the case + if ((rs1 == +0 && rs2 == -0) || (rs1 == -0 && rs2 == +0)) { + results[0] = RegisterValue(0x8000000000000000, 8); + } else { + results[0] = RegisterValue(fmin(rs1, rs2), 8); + } + + break; + } + case Opcode::RISCV_FMIN_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + // As fmin.d + if ((rs1 == +0 && rs2 == -0) || (rs1 == -0 && rs2 == +0)) { + results[0] = RegisterValue(0xffffffff80000000, 8); + } else { + results[0] = RegisterValue(NanBoxFloat(fminf(rs1, rs2)), 8); + } + + break; + } + case Opcode::RISCV_FMAX_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + // cpp fmax reference: This function is not required to be sensitive to + // the sign of zero, although some implementations additionally enforce + // that if one argument is +0 and the other is -0, then +0 is returned. + // But RISC-V spec requires this to be the case + double res; + if ((rs1 == +0 && rs2 == -0) || (rs1 == -0 && rs2 == +0)) { + res = +0; + } else { + res = fmax(rs1, rs2); + } + + results[0] = RegisterValue(res, 8); + break; + } + case Opcode::RISCV_FMAX_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + // As fmax_d + float res; + if ((rs1 == +0 && rs2 == -0) || (rs1 == -0 && rs2 == +0)) { + res = +0; + } else { + res = fmaxf(rs1, rs2); + } + + results[0] = RegisterValue(NanBoxFloat(res), 8); + break; + } + + case Opcode::RISCV_FMADD_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); + + results[0] = RegisterValue(fma(rs1, rs2, rs3), 8); + break; + } + case Opcode::RISCV_FMADD_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + const float rs3 = operands[2].get(); + + results[0] = RegisterValue(NanBoxFloat(fmaf(rs1, rs2, rs3)), 8); + break; + } + case Opcode::RISCV_FNMSUB_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); + + results[0] = RegisterValue(-(rs1 * rs2) + rs3, 8); + break; + } + case Opcode::RISCV_FNMSUB_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + const float rs3 = operands[2].get(); + + results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) + rs3), 8); + break; + } + case Opcode::RISCV_FMSUB_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + const float rs3 = operands[2].get(); + + results[0] = RegisterValue(NanBoxFloat((rs1 * rs2) - rs3), 8); + break; + } + + // // + // // // case Opcode::RISCV_FMSUB_D: { + // // // const double rs1 = operands[0].get(); + // // // const double rs2 = operands[1].get(); + // // // const double rs3 = operands[2].get(); + // // // + // // // results[0] = RegisterValue(fms(rs1, rs2, rs3), + // 8); + // // // break; + // // // } + // // // case Opcode::RISCV_FMSUB_S: { + // // // const double rs1 = operands[0].get(); + // // // const double rs2 = operands[1].get(); + // // // const double rs3 = operands[2].get(); + // // // + // // // results[0] = RegisterValue((float)fmsf(rs1, rs2, + // rs3), 4); + // // // break; + // // // } + // // + case Opcode::RISCV_FCVT_D_L: { + const int64_t rs1 = operands[0].get(); + + results[0] = RegisterValue((double)rs1, 8); + break; + } + case Opcode::RISCV_FCVT_D_W: { + const int32_t rs1 = operands[0].get(); + + results[0] = RegisterValue((double)rs1, 8); + break; + } + case Opcode::RISCV_FCVT_S_W: { + const int32_t rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + break; + } + case Opcode::RISCV_FCVT_W_D: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TONEAREST); + const double rs1 = operands[0].get(); + + if (std::isnan(rs1)) { + results[0] = RegisterValue(0x7FFFFFFF, 8); + } else { + results[0] = RegisterValue(signExtendW((uint64_t)((uint32_t)rs1)), 8); + } + break; + } + case Opcode::RISCV_FCVT_W_S: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const float rs1 = operands[0].get(); + + if (std::isnan(rs1)) { + results[0] = RegisterValue(0x7FFFFFFF, 8); + } else { + results[0] = RegisterValue(signExtendW((uint64_t)((uint32_t)rs1)), 8); + } + break; + } + + case Opcode::RISCV_FCVT_D_S: { + const float rs1 = operands[0].get(); + + results[0] = RegisterValue((double)rs1, 8); + break; + } + case Opcode::RISCV_FCVT_S_D: { + const double rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + break; + } + + case Opcode::RISCV_FSGNJ_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(std::copysign(rs1, rs2), 8); + break; + } + case Opcode::RISCV_FSGNJ_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, rs2)), 8); + break; + } + case Opcode::RISCV_FSGNJN_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); + break; + } + + case Opcode::RISCV_FSGNJN_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); + break; + } + case Opcode::RISCV_FSGNJX_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + const double xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); + + results[0] = RegisterValue(std::copysign(rs1, xorSign), 8); + break; + } + case Opcode::RISCV_FSGNJX_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + const float xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); + + results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, xorSign)), 8); + break; + } + + case Opcode::RISCV_FMV_D_X: { + const double rs1 = operands[0].get(); + + results[0] = RegisterValue(rs1, 8); + break; + } + case Opcode::RISCV_FMV_X_D: { + const double rs1 = operands[0].get(); + + results[0] = RegisterValue(rs1, 8); + break; + } + case Opcode::RISCV_FMV_W_X: { + const float rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat(rs1), 8); + break; + } + case Opcode::RISCV_FMV_X_W: { + const uint64_t rs1 = operands[0].get(); + + results[0] = RegisterValue(signExtendW(rs1), 8); + break; + } + // // + // // // TODO FLT.S and FLE.S perform what the IEEE 754-2008 + // standard + // // refers to + // // // as signaling comparisons: that is, they set the + // invalid + // // operation + // // // exception flag if either input is NaN. FEQ.S performs + // a quiet + // // // comparison: it only sets the invalid operation + // exception flag + // // if either + // // // input is a signaling NaN. For all three instructions, + // the + // // result is 0 + // // // if either operand is NaN. + case Opcode::RISCV_FEQ_D: { + // TODO FEQ.S performs a quiet + // comparison: it only sets the invalid operation exception flag if + // either input is a signaling NaN. Qemu doesn't seem to set CSR flags + // with sNANs + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } + break; + } + case Opcode::RISCV_FEQ_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } + break; + } + case Opcode::RISCV_FLT_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + if (std::isnan(rs1) || std::isnan(rs2)) { + // TODO set csr flag + } + if (rs1 < rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } + break; + } + case Opcode::RISCV_FLT_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + if (std::isnan(rs1) || std::isnan(rs2)) { + // TODO set csr flag + } + if (rs1 < rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } + break; + } + case Opcode::RISCV_FLE_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + + if (std::isnan(rs1) || std::isnan(rs2)) { + // TODO set csr flag + } + if (rs1 <= rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } + break; + } + case Opcode::RISCV_FLE_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + + if (std::isnan(rs1) || std::isnan(rs2)) { + // TODO set csr flag + } + if (rs1 <= rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { + results[0] = RegisterValue(static_cast(1), 8); + } else { + results[0] = RegisterValue(static_cast(0), 8); + } break; } diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index 9f0b594114..991c678e46 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -403,6 +403,51 @@ int64_t Linux::munmap(uint64_t addr, size_t length) { return 0; } +// TODO needs tests +uint64_t Linux::mremap(uint64_t old_address, size_t old_size, size_t new_size, + int flags, uint64_t new_address) { + LinuxProcessState* lps = &processStates_[0]; + bool MAYMOVE = flags & 1; + bool FIXED = flags & 2; + bool DONTUNMAP = flags & 4; + + // Check old address page alignment + assert(old_address == alignToBoundary(old_address, lps->pageSize) && + "mremap: old_address does not align to page boundary"); + + if (lps->contiguousAllocations.size() > 1) { + for (auto& alloc : lps->contiguousAllocations) { + // Find allocation with old_address + if (alloc.vm_start == old_address) { + // TODO If the value of old_size is zero, and old_address refers to a + // shareable mapping (see mmap(2) MAP_SHARED), then mremap() will create + // a new mapping of the same pages + + // If extended mapping will fit in the current gap + if ((alloc.vm_next->vm_start - alloc.vm_start) >= new_size) { + alloc.vm_end = alloc.vm_start + new_size; + return old_address; + } else if (MAYMOVE) { + // TODO change links + return mmap(0, new_size, -1, 34, -1, 0); + } + } + } + } else if (lps->contiguousAllocations.size() > 0) { + if (lps->contiguousAllocations[0].vm_start == old_address) { + auto& alloc = lps->contiguousAllocations[0]; + alloc.vm_end = alloc.vm_start + new_size; + return alloc.vm_start; + } else { + // old_address does not point to the one current allocation, MAP_FAILED + return -1; + } + } + + // No allocations, MAP_FAILED + return -1; +} + uint64_t Linux::mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset) { LinuxProcessState* lps = &processStates_[0]; diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 934c859202..fcc7cb37a8 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -244,7 +244,7 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - // Update registers in accoradance with the ProcessStateChange type + // Update registers in accordance with the ProcessStateChange type switch (change.type) { case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc index 074531c9f8..e16a389fd5 100644 --- a/test/regression/riscv/instructions/float.cc +++ b/test/regression/riscv/instructions/float.cc @@ -4,6 +4,8 @@ namespace { using InstFloat = RISCVRegressionTest; +// All test verified with qemu + TEST_P(InstFloat, FLD) { initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); @@ -16,6 +18,7 @@ TEST_P(InstFloat, FLD) { # Get heap address li a7, 214 ecall + fld ft0, 0(a0) fld ft1, 8(a0) fld ft2, 16(a0) @@ -28,6 +31,45 @@ TEST_P(InstFloat, FLD) { EXPECT_EQ(getFPRegister(3), 123456); } +TEST_P(InstFloat, FLW) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw ft0, 0(a0) + flw ft1, 4(a0) + flw ft2, 8(a0) + flw ft3, 12(a0) + )"); + + // Check bit values to avoid discrepancies with rounding + + EXPECT_EQ(getFPRegister(0), 0x3f800000); + EXPECT_EQ(getFPRegister(1), 0x42f6e979); + EXPECT_EQ(getFPRegister(2), 0xb9a7c5ac); + EXPECT_EQ(getFPRegister(3), 0x47f12000); + + EXPECT_EQ(getFPRegister(0), (float)1.0); + EXPECT_EQ(getFPRegister(1), (float)123.456); + EXPECT_EQ(getFPRegister(2), (float)-0.00032); + EXPECT_EQ(getFPRegister(3), (float)123456); + + // Check bit values as NaNs comparison results in false even if equivalent + + EXPECT_EQ(getFPRegister(0), 0xffffffff3f800000); + EXPECT_EQ(getFPRegister(1), 0xffffffff42f6e979); + EXPECT_EQ(getFPRegister(2), 0xffffffffb9a7c5ac); + EXPECT_EQ(getFPRegister(3), 0xffffffff47f12000); +} + TEST_P(InstFloat, FSD) { initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); @@ -37,18 +79,20 @@ TEST_P(InstFloat, FSD) { heap[3] = 123456; RUN_RISCV(R"( - # Get heap address - li a7, 214 - ecall - fld ft0, 0(a0) - fld ft1, 8(a0) - fld ft2, 16(a0) - fld ft3, 24(a0) - fsd ft3, 0(a0) - fsd ft2, 8(a0) - fsd ft1, 16(a0) - fsd ft0, 24(a0) - )"); + # Get heap address + li a7, 214 + ecall + + fld ft0, 0(a0) + fld ft1, 8(a0) + fld ft2, 16(a0) + fld ft3, 24(a0) + + fsd ft3, 0(a0) + fsd ft2, 8(a0) + fsd ft1, 16(a0) + fsd ft0, 24(a0) + )"); EXPECT_EQ(getFPRegister(0), 1.0); EXPECT_EQ(getFPRegister(1), 123.456); @@ -63,28 +107,1531 @@ TEST_P(InstFloat, FSD) { EXPECT_EQ(getMemoryValue(88), 1.0); } -TEST_P(InstFloat, FADD_D) { +TEST_P(InstFloat, FSW) { initialHeapData_.resize(32); - double* heap = reinterpret_cast(initialHeapData_.data()); + float* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 1.0; heap[1] = 123.456; heap[2] = -0.00032; heap[3] = 123456; + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld ft0, 0(a0) + fld ft1, 4(a0) + flw ft2, 8(a0) + flw ft3, 12(a0) + + fsw ft3, 0(a0) + fsw ft2, 4(a0) + fsw ft1, 8(a0) + fsw ft0, 12(a0) + )"); + + EXPECT_EQ(getFPRegister(0), 0x42f6e9793f800000); + EXPECT_EQ(getFPRegister(1), 0xb9a7c5ac42f6e979); + EXPECT_EQ(getFPRegister(2), 0xffffffffb9a7c5ac); + EXPECT_EQ(getFPRegister(3), 0xffffffff47f12000); + EXPECT_EQ(getFPRegister(2), (float)-0.00032); + EXPECT_EQ(getFPRegister(3), (float)123456); + + EXPECT_EQ(getGeneralRegister(10), 64); + + EXPECT_EQ(getMemoryValue(64), (float)123456); + EXPECT_EQ(getMemoryValue(68), (float)-0.00032); + EXPECT_EQ(getMemoryValue(72), (float)123.456); + EXPECT_EQ(getMemoryValue(76), (float)1.0); +} + +TEST_P(InstFloat, FDIV_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + RUN_RISCV(R"( # Get heap address li a7, 214 ecall - fld ft0, 0(a0) - fld ft1, 8(a0) - fld ft2, 16(a0) - fld ft3, 24(a0) - fadd.d ft4, ft0, ft1 - fadd.d ft5, ft1, ft2 - )"); - EXPECT_EQ(getFPRegister(4), 124.456); - EXPECT_EQ(getFPRegister(5), 123.456 - 0.00032); + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fdiv.d fa6, fa5, fa3 + fdiv.d ft0, fa5, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + 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); +} + +TEST_P(InstFloat, FDIV_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fdiv.s fa6, fa5, fa3 + fdiv.s ft0, fa5, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), (float)999.212341 / (float)4.52432537); + EXPECT_EQ(getFPRegister(0), (float)999.212341 / (float)-3.78900003); +} + +TEST_P(InstFloat, FMUL_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fmul.d fa6, fa5, fa3 + fmul.d ft0, fa5, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + 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); +} + +TEST_P(InstFloat, FMUL_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fmul.s fa6, fa5, fa3 + fmul.s ft0, fa5, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), (float)999.212341 * (float)4.52432537); + EXPECT_EQ(getFPRegister(0), (float)999.212341 * (float)-3.78900003); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFFC56CA040); +} + +TEST_P(InstFloat, FCVT_D_L) { + RUN_RISCV(R"( + li t0, 123 + li t1, -1 + + fcvt.d.l ft0, t0 + fcvt.d.l ft1, t1 + )"); + + EXPECT_EQ(getGeneralRegister(5), 123); + EXPECT_EQ(getGeneralRegister(6), -1); + + EXPECT_EQ(getFPRegister(0), (double)123); + EXPECT_EQ(getFPRegister(0), 0x405EC00000000000); + EXPECT_EQ(getFPRegister(1), (double)-1); + EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); +} + +TEST_P(InstFloat, FCVT_D_W) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.d.w ft0, t0 + fcvt.d.w ft1, t1 + fcvt.d.w ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (double)23456); + EXPECT_EQ(getFPRegister(0), 0x40D6E80000000000); + EXPECT_EQ(getFPRegister(1), (double)-1); + EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); + EXPECT_EQ(getFPRegister(2), (double)268435455); + EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); +} + +TEST_P(InstFloat, FCVT_S_W) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.s.w ft0, t0 + fcvt.s.w ft1, t1 + fcvt.s.w ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (float)23456); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF46b74000); + EXPECT_EQ(getFPRegister(1), (float)-1); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); + EXPECT_EQ(getFPRegister(2), (float)268435455); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4d800000); +} + +TEST_P(InstFloat, FCVT_W_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fcvt.w.d t0, fa3 # should convert to 5 + fcvt.w.d t3, fa3, rtz # should convert to 4 + fcvt.w.d t1, fa4 # should convert to -4 + fcvt.w.d t4, fa4, rtz # should convert to -3 + fcvt.w.d t2, fa6 #Nan converts to 0x7fffffff in integer reg + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getGeneralRegister(5), + 0x5); // Should round to nearest, but cpp rounds to + // zero so fails + EXPECT_EQ(getGeneralRegister(28), + 0x4); // expected to fail as functionality not implemented + EXPECT_EQ(getGeneralRegister(6), + 0xFFFFFFFFFFFFFFFC); // Should round to nearest, but cpp rounds to + // zero so fails + EXPECT_EQ( + getGeneralRegister(29), + 0xFFFFFFFFFFFFFFFD); // expected to fail as functionality not implemented + EXPECT_EQ(getGeneralRegister(7), 0x000000007FFFFFFF); +} + +TEST_P(InstFloat, FCVT_W_S) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fcvt.w.s t0, fa3 # should convert to 5 + fcvt.w.s t3, fa3, rtz # should convert to 4 + fcvt.w.s t1, fa4 # should convert to -4 + fcvt.w.s t4, fa4, rtz # should convert to -3 + fcvt.w.s t2, fa6 #Nan converts to 0x7fffffff in integer reg + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + + EXPECT_EQ(getGeneralRegister(5), + 0x5); // Should round to nearest, but cpp rounds to + // zero so fails + EXPECT_EQ(getGeneralRegister(28), + 0x4); // expected to fail as functionality not implemented + EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); + EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); + EXPECT_EQ(getGeneralRegister(7), 0x000000007FFFFFFF); +} + +TEST_P(InstFloat, FMADD_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fmadd.d fa6, fa3, fa5, fa4 + fmadd.d fa7, fa5, fa4, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + 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); +} + +TEST_P(InstFloat, FMADD_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fmadd.s fa6, fa5, fa4, fa3 # (999.212341 * -3.78900003) + 4.52432537 + fmadd.s fa7, fa4, fa3, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), + ((float)999.212341 * (float)-3.78900003) + (float)4.52432537); + EXPECT_EQ(getFPRegister(16), (float)-3781.49121); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFFC56C57DC); + EXPECT_EQ(getFPRegister(17), 0xFFFFFFFF44758476); +} + +TEST_P(InstFloat, FNMSUB_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + # Counter intuitively sums with the product + fnmsub.d fa6, fa5, fa4, fa3 # -(999.212341 * -3.78900003) + 4.52432537 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(16), + -(999.212341 * -3.78900003) + 4.52432537); +} + +TEST_P(InstFloat, FNMSUB_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + # Counter intuitively sums with the product + fnmsub.s fa6, fa5, fa4, fa3 # -(999.212341 * -3.78900003) + 4.52432537 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), + -((float)999.212341 * (float)-3.78900003) + (float)4.52432537); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF456CE8A4); +} + +TEST_P(InstFloat, FMSUB_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fmsub.s fa6, fa5, fa4, fa3 # (999.212341 * -3.78900003) - 4.52432537 + fmsub.s fa7, fa4, fa3, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), + ((float)999.212341 * (float)-3.78900003) - (float)4.52432537); + EXPECT_EQ(getFPRegister(16), (float)-3790.54004); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFFC56CE8A4); + EXPECT_EQ(getFPRegister(17), 0xFFFFFFFFC47E16B8); +} + +TEST_P(InstFloat, FCVT_D_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fcvt.d.s ft0, fa3 + fcvt.d.s ft1, fa4 + fcvt.d.s ft2, fa5 + )"); + + // Floats should be NaN boxed within 64 bit floating point registers + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(13), 0xffffffff4090c746); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(14), 0xffffffffc0727efa); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(15), 0xffffffff4479cd97); + + // Must cast to float then to double to account for representation errors. + // Can't directly cast to double + EXPECT_EQ(getFPRegister(0), (double)(float)4.52432537); + EXPECT_EQ(getFPRegister(0), 0x401218E8C0000000); + EXPECT_EQ(getFPRegister(1), (double)(float)-3.78900003); + EXPECT_EQ(getFPRegister(1), 0xC00E4FDF40000000); + EXPECT_EQ(getFPRegister(2), (double)(float)999.212341); + EXPECT_EQ(getFPRegister(2), 0x408F39B2E0000000); +} + +TEST_P(InstFloat, FCVT_S_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fcvt.s.d ft0, fa3 + fcvt.s.d ft1, fa4 + fcvt.s.d ft2, fa5 + )"); + + // Floats should be NaN boxed within 64 bit floating point registers + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(13), 0x401218E8BFF273D0); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(14), 0xC00E4FDF3F6B24E7); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(15), 0x408F39B2DFD694CD); + + EXPECT_EQ(getFPRegister(0), (float)4.52432537); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF4090c746); + EXPECT_EQ(getFPRegister(1), (float)-3.78900003); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFc0727efa); + EXPECT_EQ(getFPRegister(2), (float)999.212341); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4479cd97); +} + +TEST_P(InstFloat, FSGNJ_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fsgnj.d fa6, fa4, fa5 + fsgnj.d fa7, fa4, fa4 + fsgnj.d ft0, fa5, fa4 + fsgnj.d ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(16), (double)3.78900003); + EXPECT_EQ(getFPRegister(17), (double)-3.78900003); + EXPECT_EQ(getFPRegister(0), (double)-999.212341); + EXPECT_EQ(getFPRegister(1), (double)999.212341); + + // Pseudoinstructions fmv.d + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa4, 16(a0) + + fmv.d ft2, fa4 + fmv.d ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(2), (double)-3.78900003); + EXPECT_EQ(getFPRegister(3), (double)4.52432537); +} + +TEST_P(InstFloat, FSGNJ_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fsgnj.s fa6, fa4, fa5 + fsgnj.s fa7, fa4, fa4 + fsgnj.s ft0, fa5, fa4 + fsgnj.s ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), (float)3.78900003); + EXPECT_EQ(getFPRegister(17), (float)-3.78900003); + EXPECT_EQ(getFPRegister(0), (float)-999.212341); + EXPECT_EQ(getFPRegister(1), (float)999.212341); + + // Pseudoinstructions fmv.s + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa4, 8(a0) + + fmv.s ft2, fa4 + fmv.s ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(2), (float)-3.78900003); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFFc0727efa); + EXPECT_EQ(getFPRegister(3), (float)4.52432537); + EXPECT_EQ(getFPRegister(3), 0xFFFFFFFF4090c746); +} + +TEST_P(InstFloat, FSGNJX_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fsgnjx.d fa6, fa4, fa5 + fsgnjx.d fa7, fa4, fa4 + fsgnjx.d ft0, fa5, fa4 + fsgnjx.d ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(16), (double)-3.78900003); + EXPECT_EQ(getFPRegister(17), (double)3.78900003); + EXPECT_EQ(getFPRegister(0), (double)-999.212341); + EXPECT_EQ(getFPRegister(1), (double)999.212341); + + // Pseudoinstructions fabs.d + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa4, 16(a0) + + fabs.d ft2, fa4 + fabs.d ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(2), (double)3.78900003); + EXPECT_EQ(getFPRegister(3), (double)4.52432537); +} + +TEST_P(InstFloat, FSGNJX_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fsgnjx.s fa6, fa4, fa5 + fsgnjx.s fa7, fa4, fa4 + fsgnjx.s ft0, fa5, fa4 + fsgnjx.s ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), (float)-3.78900003); + EXPECT_EQ(getFPRegister(17), (float)3.78900003); + EXPECT_EQ(getFPRegister(0), (float)-999.212341); + EXPECT_EQ(getFPRegister(1), (float)999.212341); + + // Pseudoinstructions fabs.s + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa4, 8(a0) + + fabs.s ft2, fa4 + fabs.s ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(2), (float)3.78900003); + EXPECT_EQ(getFPRegister(3), (float)4.52432537); +} + +TEST_P(InstFloat, FSGNJN_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fsgnjn.d fa6, fa4, fa5 + fsgnjn.d fa7, fa4, fa4 + fsgnjn.d ft0, fa5, fa4 + fsgnjn.d ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + + EXPECT_EQ(getFPRegister(16), (double)-3.78900003); + EXPECT_EQ(getFPRegister(17), (double)3.78900003); + EXPECT_EQ(getFPRegister(0), (double)999.212341); + EXPECT_EQ(getFPRegister(1), (double)-999.212341); + + // Pseudoinstructions fneg.d + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa4, 16(a0) + + fneg.d ft2, fa4 + fneg.d ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(2), (double)3.78900003); + EXPECT_EQ(getFPRegister(3), (double)-4.52432537); +} + +TEST_P(InstFloat, FSGNJN_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fsgnjn.s fa6, fa4, fa5 + fsgnjn.s fa7, fa4, fa4 + fsgnjn.s ft0, fa5, fa4 + fsgnjn.s ft1, fa5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + + EXPECT_EQ(getFPRegister(16), (float)-3.78900003); + EXPECT_EQ(getFPRegister(17), (float)3.78900003); + EXPECT_EQ(getFPRegister(0), (float)999.212341); + EXPECT_EQ(getFPRegister(1), (float)-999.212341); + + // Pseudoinstructions fneg.s + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa4, 8(a0) + + fneg.s ft2, fa4 + fneg.s ft3, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(2), (float)3.78900003); + EXPECT_EQ(getFPRegister(3), (float)-4.52432537); +} + +TEST_P(InstFloat, FADD_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fadd.s ft0, fa4, fa3 + fadd.s ft1, fa5, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + + EXPECT_EQ(getFPRegister(0), (float)0.73532534); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF3f3c3e48); + EXPECT_EQ(getFPRegister(1), (float)995.423341); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF4478db18); +} + +TEST_P(InstFloat, FADD_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld ft0, 0(a0) + fld ft1, 8(a0) + fld ft2, 16(a0) + fld ft3, 24(a0) + + fadd.d ft4, ft0, ft1 + fadd.d ft5, ft1, ft2 + )"); + + EXPECT_EQ(getFPRegister(4), 124.456); + EXPECT_EQ(getFPRegister(5), 123.456 - 0.00032); +} + +TEST_P(InstFloat, FSUB_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fsub.d ft0, fa4, fa3 + fsub.d ft1, fa3, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + + EXPECT_EQ(getFPRegister(0), (double)-8.3133254); + EXPECT_EQ(getFPRegister(1), (double)8.3133254); +} + +TEST_P(InstFloat, FSUB_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fsub.s ft0, fa4, fa3 + fsub.s ft1, fa3, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + + EXPECT_EQ(getFPRegister(0), (float)-3.78900003 - (float)4.52432537); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFFc1050362); + EXPECT_EQ(getFPRegister(1), (float)4.52432537 - (float)-3.78900003); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF41050362); +} + +TEST_P(InstFloat, FSQRT_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fsqrt.d ft0, fa5 # TODO set CSR = 0b1 inexact + fsqrt.d ft1, fa4 # TODO set CSR = 0b10001 invalid op & inexact + fdiv.d fa3, fa3, fa5 # 0.00452789199 < 0 + fsqrt.d ft2, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), 4.52432537 / 999.212341); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + + EXPECT_EQ(getFPRegister(0), (double)31.6103201660470389811052882578); + EXPECT_EQ(getFPRegister(0), 0x403F9C3DF14142E6); + EXPECT_EQ(getFPRegister(1), 0x7FF8000000000000); // NaN + EXPECT_EQ(getFPRegister(2), (double)0.067289611417595679432324118352); + EXPECT_EQ(getFPRegister(2), 0x3FB139E458662CD6); +} + +TEST_P(InstFloat, FSQRT_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fsqrt.s ft0, fa5 # TODO set CSR = 0b1 inexact + fsqrt.s ft1, fa4 # TODO set CSR = 0b10001 invalid op & inexact + fdiv.s fa3, fa3, fa5 # 0.00452789199 < 0 + fsqrt.s ft2, fa3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)0.00452789199); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + + EXPECT_EQ(getFPRegister(0), (float)31.610321); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF41FCE1F0); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF7FC00000); // NaN + EXPECT_EQ(getFPRegister(2), (float)0.0672896132); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF3D89CF23); +} + +TEST_P(InstFloat, FMV_X_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa4, 16(a0) + + fmv.x.d t0, fa3 + fmv.x.d t1, fa4 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(13), 0x401218E8BFF273D0); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(14), 0xC00E4FDF3F6B24E7); + + EXPECT_EQ(getGeneralRegister(5), (double)4.52432537); + EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); + EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); + EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); +} + +TEST_P(InstFloat, FMV_X_W) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa4, 8(a0) + + fmv.x.w t0, fa3 + fmv.x.w t1, fa4 + )"); + + // Floats should be NaN boxed within 64 bit floating point registers + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(13), 0xffffffff4090c746); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(14), 0xffffffffc0727efa); + + // "float" should be sign extended when moved to integer register + EXPECT_EQ(getGeneralRegister(5), (float)4.52432537); + EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); + EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); + EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); +} + +TEST_P(InstFloat, FMV_D_X) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa4, 16(a0) + + fmv.x.d t0, fa3 + fmv.x.d t1, fa4 + + fmv.d.x fa4, t0 + fmv.d.x fa3, t1 + )"); + + EXPECT_EQ(getFPRegister(14), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), 0x401218E8BFF273D0); + EXPECT_EQ(getFPRegister(13), (double)-3.78900003); + EXPECT_EQ(getFPRegister(13), 0xC00E4FDF3F6B24E7); + + EXPECT_EQ(getGeneralRegister(5), (double)4.52432537); + EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); + EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); + EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); +} + +TEST_P(InstFloat, FMV_W_X) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa4, 8(a0) + + fmv.x.w t0, fa3 + fmv.x.w t1, fa4 + + fmv.w.x fa4, t0 + fmv.w.x fa3, t1 + )"); + + EXPECT_EQ(getFPRegister(14), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), 0xFFFFFFFF4090c746); + EXPECT_EQ(getFPRegister(13), (float)-3.78900003); + EXPECT_EQ(getFPRegister(13), 0xffffffffc0727efa); + + EXPECT_EQ(getGeneralRegister(5), (float)4.52432537); + EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); + EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); + EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); +} + +TEST_P(InstFloat, FEQ_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + feq.d t0, fa3, fa3 #equal set t0 + feq.d t1, fa3, fa4 #unequal don't set t1 + feq.d t2, fa6, fa4 #one NaN don't set t2 + feq.d t3, fa6, fa6 #both NaN don't set t3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + EXPECT_EQ(getGeneralRegister(5), 1); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); +} + +TEST_P(InstFloat, FEQ_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + feq.s t0, fa3, fa3 #equal set t0 + feq.s t1, fa3, fa4 #unequal don't set t1 + feq.s t2, fa6, fa4 #one NaN don't set t2 + feq.s t3, fa6, fa6 #both NaN don't set t3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + EXPECT_EQ(getGeneralRegister(5), 1); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); +} + +TEST_P(InstFloat, FLT_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + flt.d t0, fa3, fa3 #equal don't set t0 + flt.d t1, fa3, fa4 #fa3 (13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + EXPECT_EQ(getGeneralRegister(5), 0); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 1); +} + +TEST_P(InstFloat, FLT_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + flt.s t0, fa3, fa3 #equal don't set t0 + flt.s t1, fa3, fa4 #fa3 (13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + EXPECT_EQ(getGeneralRegister(5), 0); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 1); +} + +TEST_P(InstFloat, FLE_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fle.d t0, fa3, fa3 #equal set t0 + fle.d t1, fa3, fa4 #fa3 <=/ fa4 don't set t1 + fle.d t4, fa4, fa3 #fa4 < fa3 set t4 + fle.d t2, fa6, fa4 #one NaN don't set t2 + fle.d t3, fa6, fa6 #both NaN don't set t3 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + EXPECT_EQ(getGeneralRegister(5), 1); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 1); +} + +TEST_P(InstFloat, FLE_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fle.s t0, fa3, fa3 #equal set t0 + fle.s t1, fa3, fa4 #fa3 <=/ fa4 don't set t1 + fle.s t4, fa4, fa3 #fa4 < fa3 set t4 + fle.s t2, fa6, fa4 #one NaN don't set t2 + fle.s t3, fa6, fa6 #both NaN don't set t3 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + EXPECT_EQ(getGeneralRegister(5), 1); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 1); +} + +TEST_P(InstFloat, FMIN_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fmin.d fa0, fa3, fa4 + fmin.d fa1, fa3, fa6 # min(n, NaN) = n + fmin.d ft0, fa6, fa6 # min(NaN, NaN) = NaN + + fcvt.d.l ft1, zero + fneg.d ft2, ft1 + + fmin.d ft3, ft1, ft2 # min(+0, -0) = -0 + fmin.d ft4, ft2, ft1 # min(-0, +0) = -0 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getFPRegister(10), (double)-3.78900003); + EXPECT_EQ(getFPRegister(11), (double)4.52432537); + EXPECT_EQ(getFPRegister(0), 0x7FF8000000000000); + EXPECT_EQ(getFPRegister(3), + (double)-0); // Doesn't check for sign so below test needed + EXPECT_EQ(getFPRegister(3), 0x8000000000000000); + EXPECT_EQ(getFPRegister(4), (double)-0); + EXPECT_EQ(getFPRegister(4), 0x8000000000000000); +} + +TEST_P(InstFloat, FMIN_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fmin.s fa0, fa3, fa4 + fmin.s fa1, fa3, fa6 # min(n, NaN) = n + fmin.s ft0, fa6, fa6 # min(NaN, NaN) = NaN + + fcvt.s.w ft1, zero + fneg.s ft2, ft1 + + fmin.s ft3, ft1, ft2 # min(+0, -0) = -0 # fminf picks the later of the two options in both cases. Check our implementation fixes this + fmin.s ft4, ft2, ft1 # min(-0, +0) = -0 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xffffffff7fc00000); + + EXPECT_EQ(getFPRegister(10), (float)-3.78900003); + EXPECT_EQ(getFPRegister(11), (float)4.52432537); + EXPECT_EQ(getFPRegister(0), 0xffffffff7fc00000); + EXPECT_EQ(getFPRegister(3), + (float)-0); // Doesn't check for sign so below test needed + EXPECT_EQ(getFPRegister(3), 0xffffffff80000000); + EXPECT_EQ(getFPRegister(4), (float)-0); + EXPECT_EQ(getFPRegister(4), 0xffffffff80000000); +} + +TEST_P(InstFloat, FMAX_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fmax.d fa0, fa3, fa4 + fmax.d fa1, fa3, fa6 # max(n, NaN) = n + fmax.d ft0, fa6, fa6 # max(NaN, NaN) = NaN + + fcvt.d.l ft1, zero + fneg.d ft2, ft1 + + fmax.d ft3, ft1, ft2 # max(+0, -0) = 0 + fmax.d ft4, ft1, ft1 # max(-0, +0) = 0 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getFPRegister(10), (double)4.52432537); + EXPECT_EQ(getFPRegister(11), (double)4.52432537); + EXPECT_EQ(getFPRegister(0), 0x7FF8000000000000); + EXPECT_EQ(getFPRegister(3), (double)0); + EXPECT_EQ(getFPRegister(3), 0x0000000000000000); + EXPECT_EQ(getFPRegister(4), 0x0000000000000000); +} + +TEST_P(InstFloat, FMAX_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fmax.s fa0, fa3, fa4 + fmax.s fa1, fa3, fa6 # max(n, NaN) = n + fmax.s ft0, fa6, fa6 # max(NaN, NaN) = NaN + + fcvt.s.w ft1, zero + fneg.s ft2, ft1 + + fmax.s ft3, ft1, ft2 # max(+0, -0) = 0 + fmax.s ft4, ft2, ft1 # max(-0, +0) = 0 + + li a0, 0b111 + fsrm a0 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xffffffff7fc00000); + + EXPECT_EQ(getFPRegister(10), (float)4.52432537); + EXPECT_EQ(getFPRegister(10), 0xffffffff4090c746); + EXPECT_EQ(getFPRegister(11), (float)4.52432537); + EXPECT_EQ(getFPRegister(0), 0xffffffff7fc00000); + EXPECT_EQ(getFPRegister(3), (float)0); + EXPECT_EQ(getFPRegister(3), 0xffffffff00000000); + EXPECT_EQ(getFPRegister(4), 0xffffffff00000000); } INSTANTIATE_TEST_SUITE_P(RISCV, InstFloat, From 0b4a0e314052be7c98019faa402934c58198bfe5 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 20 Feb 2023 15:38:26 +0000 Subject: [PATCH 005/115] Finish main imlementation for all instructions and tests --- src/lib/arch/riscv/Instruction_decode.cc | 135 +++--- src/lib/arch/riscv/Instruction_execute.cc | 251 ++++++++--- test/regression/riscv/instructions/float.cc | 458 +++++++++++++++++++- 3 files changed, 725 insertions(+), 119 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 64ad5156ec..abd78b6769 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -80,55 +80,92 @@ void Instruction::invalidateIfNotImplemented() { if (metadata.opcode >= Opcode::RISCV_CSRRC && metadata.opcode <= Opcode::RISCV_CSRRWI) return; - if (metadata.opcode == Opcode::RISCV_FADD_D) return; - if (metadata.opcode == Opcode::RISCV_FADD_S) return; - if (metadata.opcode == Opcode::RISCV_FSD) return; - if (metadata.opcode == Opcode::RISCV_FSW) return; - if (metadata.opcode == Opcode::RISCV_FLD) return; - if (metadata.opcode == Opcode::RISCV_FLW) return; - if (metadata.opcode == Opcode::RISCV_FSUB_D) return; - if (metadata.opcode == Opcode::RISCV_FSUB_S) return; - if (metadata.opcode == Opcode::RISCV_FDIV_D) return; - if (metadata.opcode == Opcode::RISCV_FDIV_S) return; - if (metadata.opcode == Opcode::RISCV_FMUL_D) return; - if (metadata.opcode == Opcode::RISCV_FMUL_S) return; - if (metadata.opcode == Opcode::RISCV_FSQRT_D) return; - if (metadata.opcode == Opcode::RISCV_FSQRT_S) return; - if (metadata.opcode == Opcode::RISCV_FMIN_D) return; - if (metadata.opcode == Opcode::RISCV_FMIN_S) return; - if (metadata.opcode == Opcode::RISCV_FMAX_D) return; - if (metadata.opcode == Opcode::RISCV_FMAX_S) return; - if (metadata.opcode == Opcode::RISCV_FMADD_D) return; - if (metadata.opcode == Opcode::RISCV_FMADD_S) return; - // // if (metadata.opcode == Opcode::RISCV_FMSUB_D) return; - if (metadata.opcode == Opcode::RISCV_FNMSUB_D) return; - if (metadata.opcode == Opcode::RISCV_FNMSUB_S) return; - if (metadata.opcode == Opcode::RISCV_FMSUB_S) return; - if (metadata.opcode == Opcode::RISCV_FCVT_D_L) return; - if (metadata.opcode == Opcode::RISCV_FCVT_D_W) return; - if (metadata.opcode == Opcode::RISCV_FCVT_S_W) return; - if (metadata.opcode == Opcode::RISCV_FCVT_W_D) return; - if (metadata.opcode == Opcode::RISCV_FCVT_W_S) return; - if (metadata.opcode == Opcode::RISCV_FCVT_D_S) return; - if (metadata.opcode == Opcode::RISCV_FCVT_S_D) return; - if (metadata.opcode == Opcode::RISCV_FSGNJ_D) return; - if (metadata.opcode == Opcode::RISCV_FSGNJ_S) return; - if (metadata.opcode == Opcode::RISCV_FSGNJN_S) return; - if (metadata.opcode == Opcode::RISCV_FSGNJN_D) return; - if (metadata.opcode == Opcode::RISCV_FSGNJX_D) return; - if (metadata.opcode == Opcode::RISCV_FSGNJX_S) return; - if (metadata.opcode == Opcode::RISCV_FMV_X_D) return; - if (metadata.opcode == Opcode::RISCV_FMV_X_W) return; - if (metadata.opcode == Opcode::RISCV_FMV_D_X) return; - if (metadata.opcode == Opcode::RISCV_FMV_W_X) return; - if (metadata.opcode == Opcode::RISCV_FEQ_D) return; - if (metadata.opcode == Opcode::RISCV_FEQ_S) return; - if (metadata.opcode == Opcode::RISCV_FLT_D) return; - if (metadata.opcode == Opcode::RISCV_FLT_S) return; - if (metadata.opcode == Opcode::RISCV_FLE_D) return; - if (metadata.opcode == Opcode::RISCV_FLE_S) return; - - std::cout << "[SimEng:RISCV:Decode] Insn: " << metadata.mnemonic << " " + + if (metadata.opcode >= Opcode::RISCV_FADD_D && + metadata.opcode <= Opcode::RISCV_FADD_S) + return; + + if (metadata.opcode >= Opcode::RISCV_FCVT_D_L && + metadata.opcode <= Opcode::RISCV_FDIV_S) + return; + + if (metadata.opcode >= Opcode::RISCV_FEQ_D && + metadata.opcode <= Opcode::RISCV_FSW) + return; + + // if (metadata.opcode == Opcode::RISCV_FSD) return; + // if (metadata.opcode == Opcode::RISCV_FSW) return; + // if (metadata.opcode == Opcode::RISCV_FLD) return; + // if (metadata.opcode == Opcode::RISCV_FLW) return; + // + // if (metadata.opcode == Opcode::RISCV_FADD_D) return; + // if (metadata.opcode == Opcode::RISCV_FADD_S) return; + // if (metadata.opcode == Opcode::RISCV_FSUB_D) return; + // if (metadata.opcode == Opcode::RISCV_FSUB_S) return; + // if (metadata.opcode == Opcode::RISCV_FDIV_D) return; + // if (metadata.opcode == Opcode::RISCV_FDIV_S) return; + // if (metadata.opcode == Opcode::RISCV_FMUL_D) return; + // if (metadata.opcode == Opcode::RISCV_FMUL_S) return; + // if (metadata.opcode == Opcode::RISCV_FSQRT_D) return; + // if (metadata.opcode == Opcode::RISCV_FSQRT_S) return; + // + // if (metadata.opcode == Opcode::RISCV_FMIN_D) return; + // if (metadata.opcode == Opcode::RISCV_FMIN_S) return; + // if (metadata.opcode == Opcode::RISCV_FMAX_D) return; + // if (metadata.opcode == Opcode::RISCV_FMAX_S) return; + // + // if (metadata.opcode == Opcode::RISCV_FMADD_D) return; + // if (metadata.opcode == Opcode::RISCV_FMADD_S) return; + // if (metadata.opcode == Opcode::RISCV_FNMADD_D) return; + // if (metadata.opcode == Opcode::RISCV_FNMADD_S) return; + // if (metadata.opcode == Opcode::RISCV_FNMSUB_D) return; + // if (metadata.opcode == Opcode::RISCV_FNMSUB_S) return; + // if (metadata.opcode == Opcode::RISCV_FMSUB_S) return; + // if (metadata.opcode == Opcode::RISCV_FMSUB_D) return; + // + // if (metadata.opcode == Opcode::RISCV_FCVT_D_L) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_D_W) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_S_L) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_S_W) return; + // + // if (metadata.opcode == Opcode::RISCV_FCVT_W_D) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_W_S) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_L_D) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_L_S) return; + // + // if (metadata.opcode == Opcode::RISCV_FCVT_WU_D) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_WU_S) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_LU_D) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_LU_S) return; + // + // if (metadata.opcode == Opcode::RISCV_FCVT_D_WU) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_S_WU) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_D_LU) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_S_LU) return; + // + // if (metadata.opcode == Opcode::RISCV_FCVT_D_S) return; + // if (metadata.opcode == Opcode::RISCV_FCVT_S_D) return; + // + // if (metadata.opcode == Opcode::RISCV_FSGNJ_D) return; + // if (metadata.opcode == Opcode::RISCV_FSGNJ_S) return; + // if (metadata.opcode == Opcode::RISCV_FSGNJN_S) return; + // if (metadata.opcode == Opcode::RISCV_FSGNJN_D) return; + // if (metadata.opcode == Opcode::RISCV_FSGNJX_D) return; + // if (metadata.opcode == Opcode::RISCV_FSGNJX_S) return; + // + // if (metadata.opcode == Opcode::RISCV_FMV_X_D) return; + // if (metadata.opcode == Opcode::RISCV_FMV_X_W) return; + // if (metadata.opcode == Opcode::RISCV_FMV_D_X) return; + // if (metadata.opcode == Opcode::RISCV_FMV_W_X) return; + // + // if (metadata.opcode == Opcode::RISCV_FEQ_D) return; + // if (metadata.opcode == Opcode::RISCV_FEQ_S) return; + // if (metadata.opcode == Opcode::RISCV_FLT_D) return; + // if (metadata.opcode == Opcode::RISCV_FLT_S) return; + // if (metadata.opcode == Opcode::RISCV_FLE_D) return; + // if (metadata.opcode == Opcode::RISCV_FLE_S) return; + + std::cout << "[SimEng:RISC-V:Decode] Insn: " << metadata.mnemonic << " " << metadata.operandStr << std::endl; exception_ = InstructionException::EncodingUnallocated; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index c8425b6e5c..da25b00414 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -857,12 +857,10 @@ void Instruction::execute() { if (metadata.operands[1].reg == 2) { // TODO this won't work properly in OoO core as rounding mode could be // updated before instructions earlier in program order execute causing - // them to be rounded incorrectly - // frm - std::cerr << "CSRRW: " << metadata.mnemonic << " " - << metadata.operandStr - << ", rs1 = " << operands[0].get() - << " , rs2 = " << metadata.operands[1].reg << std::endl; + // them to be rounded incorrectly. Rounding mode needs to be set on + // commit and all subsequent instructions must be performed with updated + // mode. e.g. this should be performed atomically + switch (operands[0].get()) { case 0: fesetround(FE_TONEAREST); @@ -884,18 +882,20 @@ void Instruction::execute() { // TODO any subsequent attempt to execute a floating-point operation // with a dynamic rounding mode will raise an illegal instruction // exception. - std::cerr << "Invalid rounding mode" << std::endl; + std::cerr << "[SimEng:RISC-V:Execute] Invalid rounding mode" + << std::endl; break; } } else { - // std::cerr << "Unknown system register" << std::endl; + std::cerr << "[SimEng:RISC-V:Execute] Unknown system register" + << std::endl; } break; } - // // case Opcode::RISCV_CSRRWI: { - // // executionNYI(); - // // break; - // // } + case Opcode::RISCV_CSRRWI: { + executionNYI(); + break; + } case Opcode::RISCV_CSRRS: { // dummy implementation only used by floating point frflags, needs // capstone update to recognise system registers. No update of system @@ -904,18 +904,18 @@ void Instruction::execute() { results[0] = RegisterValue(static_cast(0), 8); break; } - // case Opcode::RISCV_CSRRSI: { - // executionNYI(); - // break; - // } - // case Opcode::RISCV_CSRRC: { - // executionNYI(); - // break; - // } - // case Opcode::RISCV_CSRRCI: { - // executionNYI(); - // break; - // } + case Opcode::RISCV_CSRRSI: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRC: { + executionNYI(); + break; + } + case Opcode::RISCV_CSRRCI: { + executionNYI(); + break; + } // TODO Apart from transfer operations described in the previous // paragraph, all other floating-point operations on narrower n-bit @@ -1134,27 +1134,31 @@ void Instruction::execute() { results[0] = RegisterValue(NanBoxFloat((rs1 * rs2) - rs3), 8); break; } + case Opcode::RISCV_FMSUB_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); + + results[0] = RegisterValue((rs1 * rs2) - rs3, 8); + break; + } + case Opcode::RISCV_FNMADD_S: { + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + const float rs3 = operands[2].get(); + + results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) - rs3), 8); + break; + } + case Opcode::RISCV_FNMADD_D: { + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); + + results[0] = RegisterValue(-(rs1 * rs2) - rs3, 8); + break; + } - // // - // // // case Opcode::RISCV_FMSUB_D: { - // // // const double rs1 = operands[0].get(); - // // // const double rs2 = operands[1].get(); - // // // const double rs3 = operands[2].get(); - // // // - // // // results[0] = RegisterValue(fms(rs1, rs2, rs3), - // 8); - // // // break; - // // // } - // // // case Opcode::RISCV_FMSUB_S: { - // // // const double rs1 = operands[0].get(); - // // // const double rs2 = operands[1].get(); - // // // const double rs3 = operands[2].get(); - // // // - // // // results[0] = RegisterValue((float)fmsf(rs1, rs2, - // rs3), 4); - // // // break; - // // // } - // // case Opcode::RISCV_FCVT_D_L: { const int64_t rs1 = operands[0].get(); @@ -1167,6 +1171,12 @@ void Instruction::execute() { results[0] = RegisterValue((double)rs1, 8); break; } + case Opcode::RISCV_FCVT_S_L: { + const int64_t rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + break; + } case Opcode::RISCV_FCVT_S_W: { const int32_t rs1 = operands[0].get(); @@ -1177,12 +1187,12 @@ void Instruction::execute() { // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TONEAREST); - const double rs1 = operands[0].get(); + const double rs1 = std::rint(operands[0].get()); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); } else { - results[0] = RegisterValue(signExtendW((uint64_t)((uint32_t)rs1)), 8); + results[0] = RegisterValue(signExtendW((int64_t)((int32_t)rs1)), 8); } break; } @@ -1195,10 +1205,134 @@ void Instruction::execute() { if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); } else { - results[0] = RegisterValue(signExtendW((uint64_t)((uint32_t)rs1)), 8); + results[0] = RegisterValue(signExtendW((int64_t)((int32_t)rs1)), 8); } break; } + case Opcode::RISCV_FCVT_L_D: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TONEAREST); + const double rs1 = std::rint(operands[0].get()); + + if (std::isnan(rs1)) { + results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); + } else { + results[0] = RegisterValue((int64_t)rs1, 8); + } + break; + } + case Opcode::RISCV_FCVT_L_S: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const float rs1 = operands[0].get(); + + if (std::isnan(rs1)) { + results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); + } else { + results[0] = RegisterValue((int64_t)rs1, 8); + } + break; + } + case Opcode::RISCV_FCVT_WU_D: { + // TODO need to take rounding mode into + // account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const double rs1 = operands[0].get(); + + if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { + results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); + } else { + if (rs1 < 0) { + // TODO set CSR flags + results[0] = RegisterValue((uint64_t)0, 8); + } else { + results[0] = RegisterValue(signExtendW((uint64_t)(uint32_t)rs1), 8); + } + } + break; + } + case Opcode::RISCV_FCVT_WU_S: { + // TODO need to take rounding mode into + // account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const float rs1 = operands[0].get(); + + if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { + results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); + } else { + if (rs1 < 0) { + // TODO set CSR flags + results[0] = RegisterValue((uint64_t)0, 8); + } else { + results[0] = RegisterValue(signExtendW((uint64_t)(uint32_t)rs1), 8); + } + } + break; + } + case Opcode::RISCV_FCVT_LU_D: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const double rs1 = operands[0].get(); + + if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { + results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); + } else { + if (rs1 < 0) { + // TODO set CSR flags + results[0] = RegisterValue((uint64_t)0, 8); + } else { + results[0] = RegisterValue((uint64_t)rs1, 8); + } + } + break; + } + case Opcode::RISCV_FCVT_LU_S: { + // TODO need to take rounding mode into account, +- INF + // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TOWARDZERO); + const float rs1 = operands[0].get(); + + if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { + results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); + } else { + if (rs1 < 0) { + // TODO set CSR flags + results[0] = RegisterValue((uint64_t)0, 8); + } else { + results[0] = RegisterValue((uint64_t)rs1, 8); + } + } + break; + } + case Opcode::RISCV_FCVT_D_WU: { + const uint32_t rs1 = operands[0].get(); + + results[0] = RegisterValue((double)rs1, 8); + break; + } + case Opcode::RISCV_FCVT_S_WU: { + const uint32_t rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + break; + } + case Opcode::RISCV_FCVT_D_LU: { + const uint64_t rs1 = operands[0].get(); + + results[0] = RegisterValue((double)rs1, 8); + break; + } + case Opcode::RISCV_FCVT_S_LU: { + const uint64_t rs1 = operands[0].get(); + + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + break; + } case Opcode::RISCV_FCVT_D_S: { const float rs1 = operands[0].get(); @@ -1285,22 +1419,13 @@ void Instruction::execute() { results[0] = RegisterValue(signExtendW(rs1), 8); break; } - // // - // // // TODO FLT.S and FLE.S perform what the IEEE 754-2008 - // standard - // // refers to - // // // as signaling comparisons: that is, they set the - // invalid - // // operation - // // // exception flag if either input is NaN. FEQ.S performs - // a quiet - // // // comparison: it only sets the invalid operation - // exception flag - // // if either - // // // input is a signaling NaN. For all three instructions, - // the - // // result is 0 - // // // if either operand is NaN. + + // TODO FLT.S and FLE.S perform what the IEEE 754-2008 standard refers to + // as signaling comparisons: that is, they set the invalid operation + // exception flag if either input is NaN. FEQ.S performs a quiet + // comparison: it only sets the invalid operation exception flag if either + // input is a signaling NaN. For all three instructions, the result is 0 + // if either operand is NaN. case Opcode::RISCV_FEQ_D: { // TODO FEQ.S performs a quiet // comparison: it only sets the invalid operation exception flag if diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc index e16a389fd5..778678095f 100644 --- a/test/regression/riscv/instructions/float.cc +++ b/test/regression/riscv/instructions/float.cc @@ -300,6 +300,29 @@ TEST_P(InstFloat, FCVT_D_W) { EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); } +TEST_P(InstFloat, FCVT_S_L) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.s.l ft0, t0 + fcvt.s.l ft1, t1 + fcvt.s.l ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (float)23456); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF46b74000); + EXPECT_EQ(getFPRegister(1), (float)-1); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); + EXPECT_EQ(getFPRegister(2), (float)-4026531841); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFFCF700000); +} + TEST_P(InstFloat, FCVT_S_W) { RUN_RISCV(R"( li t0, 23456 @@ -406,6 +429,331 @@ TEST_P(InstFloat, FCVT_W_S) { EXPECT_EQ(getGeneralRegister(7), 0x000000007FFFFFFF); } +TEST_P(InstFloat, FCVT_L_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fcvt.l.d t0, fa3 # should convert to 5 + fcvt.l.d t3, fa3, rtz # should convert to 4 + fcvt.l.d t1, fa4 # should convert to -4 + fcvt.l.d t4, fa4, rtz # should convert to -3 + fcvt.l.d t2, fa6 #Nan converts to 0x7fffffff in integer reg + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); + EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); + EXPECT_EQ(getGeneralRegister(7), 0x7FFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_L_S) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fcvt.l.s t0, fa3 # should convert to 5 + fcvt.l.s t3, fa3, rtz # should convert to 4 + fcvt.l.s t1, fa4 # should convert to -4 + fcvt.l.s t4, fa4, rtz # should convert to -3 + fcvt.l.s t2, fa6 #Nan converts to 0x7fffffff in integer reg + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); + EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); + EXPECT_EQ(getGeneralRegister(7), 0x7FFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_LU_D) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 1.8446744073709552e+19; // 2^64 - 1 + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fcvt.lu.d t0, fa3 # should convert to 5 + fcvt.lu.d t3, fa3, rtz # should convert to 4 + fcvt.lu.d t1, fa4 # should convert to 0 + fcvt.lu.d t4, fa4, rtz # should convert to 0 + fcvt.lu.d t2, fa6 #Nan converts to 0x7fffffff in integer reg + fcvt.lu.d t5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), 0x43F0000000000000); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_WU_D) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 1.8446744073709552e+19; // 2^64 - 1 + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + fld fa6, 24(a0) + + fcvt.wu.d t0, fa3 # should convert to 5 + fcvt.wu.d t3, fa3, rtz # should convert to 4 + fcvt.wu.d t1, fa4 # should convert to 0 + fcvt.wu.d t4, fa4, rtz # should convert to 0 + fcvt.wu.d t2, fa6 #Nan converts to 0x7fffffff in integer reg + fcvt.wu.d t5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), 0x43F0000000000000); + EXPECT_EQ(getFPRegister(16), 0x7FF8000000000000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_LU_S) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 1.8446744073709552e+19; // 2^64 - 1 + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fcvt.lu.s t0, fa3 # should convert to 5 + fcvt.lu.s t3, fa3, rtz # should convert to 4 + fcvt.lu.s t1, fa4 # should convert to 0 + fcvt.lu.s t4, fa4, rtz # should convert to 0 + fcvt.lu.s t2, fa6 #Nan converts to 0x7fffffff in integer reg + fcvt.lu.s t5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), 0xFFFFFFFF5F800000); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_WU_S) { + // TODO expected to fail as rounding modes not implemented + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 1.8446744073709552e+19; // 2^64 - 1 + heap[2] = -3.78900003; + heap[3] = std::nan("0"); + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + flw fa6, 12(a0) + + fcvt.wu.s t0, fa3 # should convert to 5 + fcvt.wu.s t3, fa3, rtz # should convert to 4 + fcvt.wu.s t1, fa4 # should convert to 0 + fcvt.wu.s t4, fa4, rtz # should convert to 0 + fcvt.wu.s t2, fa6 #Nan converts to 0x7fffffff in integer reg + fcvt.wu.s t5, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), 0xFFFFFFFF5F800000); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF7FC00000); + + EXPECT_EQ(getGeneralRegister(5), 0x5); + EXPECT_EQ(getGeneralRegister(28), 0x4); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); +} + +TEST_P(InstFloat, FCVT_D_WU) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.d.wu ft0, t0 + fcvt.d.wu ft1, t1 + fcvt.d.wu ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (double)23456); + EXPECT_EQ(getFPRegister(0), 0x40D6E80000000000); + EXPECT_EQ(getFPRegister(1), (double)4294967295); + EXPECT_EQ(getFPRegister(1), 0x41EFFFFFFFE00000); + EXPECT_EQ(getFPRegister(2), (double)268435455); + EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); +} + +TEST_P(InstFloat, FCVT_S_WU) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.s.wu ft0, t0 + fcvt.s.wu ft1, t1 + fcvt.s.wu ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (float)23456); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF46b74000); + EXPECT_EQ(getFPRegister(1), (float)4294967295); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF4F800000); + EXPECT_EQ(getFPRegister(2), (float)268435456); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4D800000); +} + +TEST_P(InstFloat, FCVT_D_LU) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.d.lu ft0, t0 + fcvt.d.lu ft1, t1 + fcvt.d.lu ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (double)23456); + EXPECT_EQ(getFPRegister(0), 0x40D6E80000000000); + EXPECT_EQ(getFPRegister(1), (double)1.8446744073709551616e+19); + EXPECT_EQ(getFPRegister(1), 0x43F0000000000000); + EXPECT_EQ(getFPRegister(2), (double)1.8446744069683019776e+19); + EXPECT_EQ(getFPRegister(2), 0x43EFFFFFFFE20000); +} + +TEST_P(InstFloat, FCVT_S_LU) { + RUN_RISCV(R"( + li t0, 23456 + li t1, -1 + li t2, 0xFFFFFFFF0FFFFFFF + + fcvt.s.lu ft0, t0 + fcvt.s.lu ft1, t1 + fcvt.s.lu ft2, t2 + )"); + + EXPECT_EQ(getGeneralRegister(5), 23456); + EXPECT_EQ(getGeneralRegister(6), -1); + EXPECT_EQ(getGeneralRegister(7), -4026531841); + + EXPECT_EQ(getFPRegister(0), (float)23456); + EXPECT_EQ(getFPRegister(0), 0xFFFFFFFF46b74000); + EXPECT_EQ(getFPRegister(1), (float)1.84467440737e+19); + EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF5F800000); + EXPECT_EQ(getFPRegister(2), (float)1.84467440737e+19); + EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF5F800000); +} + TEST_P(InstFloat, FMADD_D) { initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); @@ -551,6 +899,101 @@ TEST_P(InstFloat, FMSUB_S) { EXPECT_EQ(getFPRegister(17), 0xFFFFFFFFC47E16B8); } +TEST_P(InstFloat, FMSUB_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fmsub.d fa6, fa5, fa4, fa3 # (999.212341 * -3.78900003) - 4.52432537 + fmsub.d fa7, fa4, fa3, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(16), + ((double)999.212341 * (double)-3.78900003) - (double)4.52432537); + EXPECT_EQ(getFPRegister(16), + (double)-3790.5399153953703716979362070560455322265625); + EXPECT_EQ(getFPRegister(16), 0xC0AD9D146FCA6B72); + EXPECT_EQ(getFPRegister(17), 0xC08FC2D70F769B06); +} + +TEST_P(InstFloat, FNMADD_S) { + initialHeapData_.resize(32); + float* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + flw fa3, 0(a0) + flw fa5, 4(a0) + flw fa4, 8(a0) + + fnmadd.s fa6, fa5, fa4, fa3 # -(999.212341 * -3.78900003) - 4.52432537 + fnmadd.s fa7, fa4, fa3, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (float)4.52432537); + EXPECT_EQ(getFPRegister(14), (float)-3.78900003); + EXPECT_EQ(getFPRegister(15), (float)999.212341); + EXPECT_EQ(getFPRegister(16), + -((float)999.212341 * (float)-3.78900003) - (float)4.52432537); + EXPECT_EQ(getFPRegister(16), (float)3781.4912646554); + EXPECT_EQ(getFPRegister(16), 0xFFFFFFFF456c57dc); + EXPECT_EQ(getFPRegister(17), 0xFFFFFFFFc4758476); +} + +TEST_P(InstFloat, FNMADD_D) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 4.52432537; + heap[1] = 999.212341; + heap[2] = -3.78900003; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + fld fa3, 0(a0) + fld fa5, 8(a0) + fld fa4, 16(a0) + + fnmadd.d fa6, fa5, fa4, fa3 # -(999.212341 * -3.78900003) - 4.52432537 + fnmadd.d fa7, fa4, fa3, fa5 + )"); + + EXPECT_EQ(getFPRegister(13), (double)4.52432537); + EXPECT_EQ(getFPRegister(14), (double)-3.78900003); + EXPECT_EQ(getFPRegister(15), (double)999.212341); + EXPECT_EQ(getFPRegister(16), + -((double)999.212341 * (double)-3.78900003) - (double)4.52432537); + EXPECT_EQ(getFPRegister(16), + (double)3781.4912646553702870733104646205902099609375); + EXPECT_EQ(getFPRegister(16), 0x40AD8AFB870A78FE); + EXPECT_EQ(getFPRegister(17), 0xC08EB08EB0368E94); +} + TEST_P(InstFloat, FCVT_D_S) { initialHeapData_.resize(32); float* heap = reinterpret_cast(initialHeapData_.data()); @@ -1616,9 +2059,6 @@ TEST_P(InstFloat, FMAX_S) { fmax.s ft3, ft1, ft2 # max(+0, -0) = 0 fmax.s ft4, ft2, ft1 # max(-0, +0) = 0 - - li a0, 0b111 - fsrm a0 )"); EXPECT_EQ(getFPRegister(13), (float)4.52432537); @@ -1634,9 +2074,13 @@ TEST_P(InstFloat, FMAX_S) { EXPECT_EQ(getFPRegister(4), 0xffffffff00000000); } -INSTANTIATE_TEST_SUITE_P(RISCV, InstFloat, - ::testing::Values(std::make_tuple(EMULATION, - YAML::Load("{}"))), - paramToString); +INSTANTIATE_TEST_SUITE_P( + RISCV, InstFloat, + ::testing::Values( + std::make_tuple(EMULATION, YAML::Load("{}")) + // std::make_tuple(INORDER, YAML::Load("{}")), + // std::make_tuple(OUTOFORDER, YAML::Load("{}")) + ), + paramToString); } // namespace \ No newline at end of file From 6a543776ca8fda3c6c39c800a383f0696100e117 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 20 Feb 2023 16:15:04 +0000 Subject: [PATCH 006/115] Add comment to each execution case and improve ordering --- src/lib/arch/riscv/Instruction_execute.cc | 148 +++++++++++----------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index da25b00414..0665bb9e9e 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -851,7 +851,7 @@ void Instruction::execute() { // Do not read-modify-write ATOMICALLY // Left unimplemented due to Capstone being unable to disassemble CSR // addresses - case Opcode::RISCV_CSRRW: { + case Opcode::RISCV_CSRRW: { // CSRRW rd,csr,rs1 // Do nothing to allow progression if (metadata.operands[1].reg == 2) { @@ -892,11 +892,11 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_CSRRWI: { + case Opcode::RISCV_CSRRWI: { // CSRRWI rd,csr,imm executionNYI(); break; } - case Opcode::RISCV_CSRRS: { + case Opcode::RISCV_CSRRS: { // CSRRS rd,csr,rs1 // dummy implementation only used by floating point frflags, needs // capstone update to recognise system registers. No update of system // register as rs1 == zero @@ -904,15 +904,15 @@ void Instruction::execute() { results[0] = RegisterValue(static_cast(0), 8); break; } - case Opcode::RISCV_CSRRSI: { + case Opcode::RISCV_CSRRSI: { // CSRRSI rd,csr,imm executionNYI(); break; } - case Opcode::RISCV_CSRRC: { + case Opcode::RISCV_CSRRC: { // CSRRC rd,csr,rs1 executionNYI(); break; } - case Opcode::RISCV_CSRRCI: { + case Opcode::RISCV_CSRRCI: { // CSRRCI rd,csr,imm executionNYI(); break; } @@ -955,58 +955,56 @@ void Instruction::execute() { results[0] = RegisterValue(rs1 + rs2, 8); break; } - case Opcode::RISCV_FADD_S: { + case Opcode::RISCV_FADD_S: { // FADD.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(NanBoxFloat(rs1 + rs2), 8); break; } - case Opcode::RISCV_FSUB_D: { + case Opcode::RISCV_FSUB_D: { // FSUB.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 - rs2, 8); break; } - case Opcode::RISCV_FSUB_S: { + case Opcode::RISCV_FSUB_S: { // FSUB.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(NanBoxFloat(rs1 - rs2), 8); break; } - case Opcode::RISCV_FDIV_D: { + case Opcode::RISCV_FDIV_D: { // FDIV.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 / rs2, 8); break; } - case Opcode::RISCV_FDIV_S: { + case Opcode::RISCV_FDIV_S: { // FDIV.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(NanBoxFloat(rs1 / rs2), 8); break; } - - case Opcode::RISCV_FMUL_D: { + case Opcode::RISCV_FMUL_D: { // FMUL.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 * rs2, 8); break; } - case Opcode::RISCV_FMUL_S: { + case Opcode::RISCV_FMUL_S: { // FMUL.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(NanBoxFloat(rs1 * rs2), 8); break; } - - case Opcode::RISCV_FSQRT_D: { + case Opcode::RISCV_FSQRT_D: { // FSQRT.D rd,rs1 const double rs1 = operands[0].get(); const double sqrtAns = sqrt(rs1); @@ -1018,7 +1016,7 @@ void Instruction::execute() { results[0] = RegisterValue(res, 8); break; } - case Opcode::RISCV_FSQRT_S: { + case Opcode::RISCV_FSQRT_S: { // FSQRT.S rd,rs1 const float rs1 = operands[0].get(); const float sqrtAns = sqrtf(rs1); @@ -1031,7 +1029,7 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FMIN_D: { + case Opcode::RISCV_FMIN_D: { // FMIN.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1047,7 +1045,7 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FMIN_S: { + case Opcode::RISCV_FMIN_S: { // FMIN.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); @@ -1060,7 +1058,7 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FMAX_D: { + case Opcode::RISCV_FMAX_D: { // FMAX.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1078,7 +1076,7 @@ void Instruction::execute() { results[0] = RegisterValue(res, 8); break; } - case Opcode::RISCV_FMAX_S: { + case Opcode::RISCV_FMAX_S: { // FMAX.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); @@ -1094,7 +1092,7 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FMADD_D: { + case Opcode::RISCV_FMADD_D: { // FMADD.D rd,rs1,rs2,rs3 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); const double rs3 = operands[2].get(); @@ -1102,7 +1100,7 @@ void Instruction::execute() { results[0] = RegisterValue(fma(rs1, rs2, rs3), 8); break; } - case Opcode::RISCV_FMADD_S: { + case Opcode::RISCV_FMADD_S: { // FMADD.S rd,rs1,rs2,rs3 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); const float rs3 = operands[2].get(); @@ -1110,7 +1108,7 @@ void Instruction::execute() { results[0] = RegisterValue(NanBoxFloat(fmaf(rs1, rs2, rs3)), 8); break; } - case Opcode::RISCV_FNMSUB_D: { + case Opcode::RISCV_FNMSUB_D: { // FNMSUB.D rd,rs1,rs2,rs3 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); const double rs3 = operands[2].get(); @@ -1118,7 +1116,7 @@ void Instruction::execute() { results[0] = RegisterValue(-(rs1 * rs2) + rs3, 8); break; } - case Opcode::RISCV_FNMSUB_S: { + case Opcode::RISCV_FNMSUB_S: { // FNMSUB.S rd,rs1,rs2,rs3 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); const float rs3 = operands[2].get(); @@ -1126,15 +1124,7 @@ void Instruction::execute() { results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) + rs3), 8); break; } - case Opcode::RISCV_FMSUB_S: { - const float rs1 = operands[0].get(); - const float rs2 = operands[1].get(); - const float rs3 = operands[2].get(); - - results[0] = RegisterValue(NanBoxFloat((rs1 * rs2) - rs3), 8); - break; - } - case Opcode::RISCV_FMSUB_D: { + case Opcode::RISCV_FMSUB_D: { // FMSUB.D rd,rs1,rs2,rs3 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); const double rs3 = operands[2].get(); @@ -1142,15 +1132,15 @@ void Instruction::execute() { results[0] = RegisterValue((rs1 * rs2) - rs3, 8); break; } - case Opcode::RISCV_FNMADD_S: { + case Opcode::RISCV_FMSUB_S: { // FMSUB.S rd,rs1,rs2,rs3 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); const float rs3 = operands[2].get(); - results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) - rs3), 8); + results[0] = RegisterValue(NanBoxFloat((rs1 * rs2) - rs3), 8); break; } - case Opcode::RISCV_FNMADD_D: { + case Opcode::RISCV_FNMADD_D: { // FNMADD.D rd,rs1,rs2,rs3 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); const double rs3 = operands[2].get(); @@ -1158,32 +1148,40 @@ void Instruction::execute() { results[0] = RegisterValue(-(rs1 * rs2) - rs3, 8); break; } + case Opcode::RISCV_FNMADD_S: { // FNMADD.S rd,rs1,rs2,rs3 + const float rs1 = operands[0].get(); + const float rs2 = operands[1].get(); + const float rs3 = operands[2].get(); + + results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) - rs3), 8); + break; + } - case Opcode::RISCV_FCVT_D_L: { + case Opcode::RISCV_FCVT_D_L: { // FCVT.D.L rd,rs1 const int64_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); break; } - case Opcode::RISCV_FCVT_D_W: { + case Opcode::RISCV_FCVT_D_W: { // FCVT.D.W rd,rs1 const int32_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); break; } - case Opcode::RISCV_FCVT_S_L: { + case Opcode::RISCV_FCVT_S_L: { // FCVT.S.L rd,rs1 const int64_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } - case Opcode::RISCV_FCVT_S_W: { + case Opcode::RISCV_FCVT_S_W: { // FCVT.S.W rd,rs1 const int32_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } - case Opcode::RISCV_FCVT_W_D: { + case Opcode::RISCV_FCVT_W_D: { // FCVT.W.D rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TONEAREST); @@ -1196,7 +1194,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_W_S: { + case Opcode::RISCV_FCVT_W_S: { // FCVT.W.S rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TOWARDZERO); @@ -1209,7 +1207,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_L_D: { + case Opcode::RISCV_FCVT_L_D: { // FCVT.L.D rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TONEAREST); @@ -1222,7 +1220,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_L_S: { + case Opcode::RISCV_FCVT_L_S: { // FCVT.L.S rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TOWARDZERO); @@ -1235,7 +1233,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_WU_D: { + case Opcode::RISCV_FCVT_WU_D: { // FCVT.WU.D rd,rs1 // TODO need to take rounding mode into // account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round @@ -1254,7 +1252,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_WU_S: { + case Opcode::RISCV_FCVT_WU_S: { // FCVT.WU.S rd,rs1 // TODO need to take rounding mode into // account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round @@ -1273,7 +1271,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_LU_D: { + case Opcode::RISCV_FCVT_LU_D: { // FCVT.LU.D rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TOWARDZERO); @@ -1291,7 +1289,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_LU_S: { + case Opcode::RISCV_FCVT_LU_S: { // FCVT.LU.S rd,rs1 // TODO need to take rounding mode into account, +- INF // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round // std::fesetround(FE_TOWARDZERO); @@ -1309,59 +1307,59 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FCVT_D_WU: { - const uint32_t rs1 = operands[0].get(); + case Opcode::RISCV_FCVT_D_LU: { // FCVT.D.LU rd,rs1 + const uint64_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); break; } - case Opcode::RISCV_FCVT_S_WU: { + case Opcode::RISCV_FCVT_D_WU: { // FCVT.D.WU rd,rs1 const uint32_t rs1 = operands[0].get(); - results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); + results[0] = RegisterValue((double)rs1, 8); break; } - case Opcode::RISCV_FCVT_D_LU: { + case Opcode::RISCV_FCVT_S_LU: { // FCVT.S.LU rd,rs1 const uint64_t rs1 = operands[0].get(); - results[0] = RegisterValue((double)rs1, 8); + results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } - case Opcode::RISCV_FCVT_S_LU: { - const uint64_t rs1 = operands[0].get(); + case Opcode::RISCV_FCVT_S_WU: { // FCVT.S.WU rd,rs1 + const uint32_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } - case Opcode::RISCV_FCVT_D_S: { + case Opcode::RISCV_FCVT_D_S: { // FCVT.D.S rd,rs1 const float rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); break; } - case Opcode::RISCV_FCVT_S_D: { + case Opcode::RISCV_FCVT_S_D: { // FCVT.S.D rd,rs1 const double rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } - case Opcode::RISCV_FSGNJ_D: { + case Opcode::RISCV_FSGNJ_D: { // FSGNJ.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); results[0] = RegisterValue(std::copysign(rs1, rs2), 8); break; } - case Opcode::RISCV_FSGNJ_S: { + case Opcode::RISCV_FSGNJ_S: { // FSGNJ.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, rs2)), 8); break; } - case Opcode::RISCV_FSGNJN_D: { + case Opcode::RISCV_FSGNJN_D: { // FSGNJN.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1369,14 +1367,14 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FSGNJN_S: { + case Opcode::RISCV_FSGNJN_S: { // FSGNJN.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); break; } - case Opcode::RISCV_FSGNJX_D: { + case Opcode::RISCV_FSGNJX_D: { // FSGNJX.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1385,7 +1383,7 @@ void Instruction::execute() { results[0] = RegisterValue(std::copysign(rs1, xorSign), 8); break; } - case Opcode::RISCV_FSGNJX_S: { + case Opcode::RISCV_FSGNJX_S: { // FSGNJX.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); @@ -1395,25 +1393,25 @@ void Instruction::execute() { break; } - case Opcode::RISCV_FMV_D_X: { + case Opcode::RISCV_FMV_D_X: { // FMV.D.X rd,rs1 const double rs1 = operands[0].get(); results[0] = RegisterValue(rs1, 8); break; } - case Opcode::RISCV_FMV_X_D: { + case Opcode::RISCV_FMV_X_D: { // FMV.X.D rd,rs1 const double rs1 = operands[0].get(); results[0] = RegisterValue(rs1, 8); break; } - case Opcode::RISCV_FMV_W_X: { + case Opcode::RISCV_FMV_W_X: { // FMV.W.X rd,rs1 const float rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat(rs1), 8); break; } - case Opcode::RISCV_FMV_X_W: { + case Opcode::RISCV_FMV_X_W: { // FMV.X.W rd,rs1 const uint64_t rs1 = operands[0].get(); results[0] = RegisterValue(signExtendW(rs1), 8); @@ -1426,7 +1424,7 @@ void Instruction::execute() { // comparison: it only sets the invalid operation exception flag if either // input is a signaling NaN. For all three instructions, the result is 0 // if either operand is NaN. - case Opcode::RISCV_FEQ_D: { + case Opcode::RISCV_FEQ_D: { // FEQ.D rd,rs1,rs2 // TODO FEQ.S performs a quiet // comparison: it only sets the invalid operation exception flag if // either input is a signaling NaN. Qemu doesn't seem to set CSR flags @@ -1441,7 +1439,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FEQ_S: { + case Opcode::RISCV_FEQ_S: { // FEQ.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); @@ -1452,7 +1450,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FLT_D: { + case Opcode::RISCV_FLT_D: { // FLT.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1466,7 +1464,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FLT_S: { + case Opcode::RISCV_FLT_S: { // FLT.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); @@ -1480,7 +1478,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FLE_D: { + case Opcode::RISCV_FLE_D: { // FLE.D rd,rs1,rs2 const double rs1 = operands[0].get(); const double rs2 = operands[1].get(); @@ -1494,7 +1492,7 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_FLE_S: { + case Opcode::RISCV_FLE_S: { // FLE.S rd,rs1,rs2 const float rs1 = operands[0].get(); const float rs2 = operands[1].get(); From 035108a148e66884e8c7d9bad6183a15257293bc Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 20 Feb 2023 17:09:33 +0000 Subject: [PATCH 007/115] Improve NaNbox logic --- src/include/simeng/RegisterValue.hh | 2 +- src/lib/arch/riscv/Instruction_execute.cc | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/include/simeng/RegisterValue.hh b/src/include/simeng/RegisterValue.hh index 20004432d0..1a0c37dd98 100644 --- a/src/include/simeng/RegisterValue.hh +++ b/src/include/simeng/RegisterValue.hh @@ -90,7 +90,7 @@ class RegisterValue { * the specified datatype. */ template const T* getAsVector() const { - static_assert(alignof(T) <= 8 && "Alignment over 8 bytes not guranteed"); + static_assert(alignof(T) <= 8 && "Alignment over 8 bytes not guaranteed"); assert(bytes > 0 && "Attempted to access an uninitialised RegisterValue"); assert(sizeof(T) <= bytes && "Attempted to access a RegisterValue as a datatype larger than the " diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 0665bb9e9e..c792bd7371 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -18,12 +18,13 @@ uint64_t NanBox(uint32_t floatAsUint) { } uint64_t NanBoxFloat(float f) { - // TODO there must be a better way - float* fp = (float*)malloc(sizeof(float)); - *fp = f; - uint64_t boxed = NanBox(*reinterpret_cast(fp)); - free(fp); - return boxed; + static_assert(sizeof(float) == 4 && "Float not of size 4 bytes"); + + uint64_t box{0xffffffff00000000}; + std::memcpy(reinterpret_cast(&box), reinterpret_cast(&f), + sizeof(float)); + + return box; } /** Multiply unsigned `a` and unsigned `b`, and return the high 64 bits of the From e2259d79ac5ad2404147d7ebab3ce8502d30fefb Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Feb 2023 11:30:29 +0000 Subject: [PATCH 008/115] Correctly tag multiply, divide and floating point instructions --- src/include/simeng/arch/riscv/Instruction.hh | 8 +++--- src/lib/arch/riscv/Instruction.cc | 1 + src/lib/arch/riscv/Instruction_decode.cc | 28 ++++++++++++++++++-- src/lib/arch/riscv/Instruction_execute.cc | 12 +++------ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index cb401c4399..8b7a7d1a25 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -145,6 +145,9 @@ class Instruction : public simeng::Instruction { /** Is this an atomic instruction? */ bool isAtomic() const; + /** Is this a floating point operation? */ + bool isFloat() const; + /** Retrieve the instruction group this instruction belongs to. */ uint16_t getGroup() const override; @@ -163,9 +166,6 @@ class Instruction : public simeng::Instruction { * automatically supplied as zero. */ static const Register ZERO_REGISTER; - /** Canonical 64-bit NaN defined by IEEE 754*/ - static const uint64_t UPPER_32_ALL_1 = 0xFFFFFFFF00000000; - private: /** The maximum number of source registers any supported RISC-V instruction * can have. */ @@ -241,6 +241,8 @@ class Instruction : public simeng::Instruction { bool isLogical_ = false; /** Is this a compare instruction? */ bool isCompare_ = false; + /** Is this a floating point operation? */ + bool isFloat_ = false; // Memory /** Set the accessed memory addresses, and create a corresponding memory data diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 530890e9a6..686034650a 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -100,6 +100,7 @@ bool Instruction::isStoreData() const { return isStore_; } bool Instruction::isLoad() const { return isLoad_; } bool Instruction::isBranch() const { return isBranch_; } bool Instruction::isAtomic() const { return isAtomic_; } +bool Instruction::isFloat() const { return isFloat_; } void Instruction::setMemoryAddresses( const std::vector& addresses) { diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index abd78b6769..2cf3e12c7c 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -239,8 +239,10 @@ void Instruction::decode() { break; } - if (Opcode::RISCV_AMOADD_D <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_AMOXOR_W_RL) { + if ((Opcode::RISCV_AMOADD_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_AMOXOR_W_RL) || + (Opcode::RISCV_CSRRC <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_CSRRWI)) { // Atomics: both load and store isLoad_ = true; isStore_ = true; @@ -351,6 +353,28 @@ void Instruction::decode() { isCompare_ = true; } + if ((Opcode::RISCV_MUL <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_MULW)) { + // Compare instructions + isMultiply_ = true; + } + + if (((Opcode::RISCV_REM <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_REMW) || + (Opcode::RISCV_DIV <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_DIVW))) { + // Compare instructions + isDivide_ = true; + } + + if ((metadata.opcode >= Opcode::RISCV_FADD_D && + metadata.opcode <= Opcode::RISCV_FDIV_S) || + (metadata.opcode >= Opcode::RISCV_FEQ_D && + metadata.opcode <= Opcode::RISCV_FSW)) { + // Floating point operation + isFloat_ = true; + } + // Set branch type switch (metadata.opcode) { case Opcode::RISCV_BEQ: diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index c792bd7371..d909899b4c 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -13,14 +13,10 @@ namespace riscv { /** NaN box single precision floating point values as defined in * riscv-spec-20191213 page 73 */ -uint64_t NanBox(uint32_t floatAsUint) { - return Instruction::UPPER_32_ALL_1 | static_cast(floatAsUint); -} - uint64_t NanBoxFloat(float f) { static_assert(sizeof(float) == 4 && "Float not of size 4 bytes"); - uint64_t box{0xffffffff00000000}; + uint64_t box = 0xffffffff00000000; std::memcpy(reinterpret_cast(&box), reinterpret_cast(&f), sizeof(float)); @@ -95,7 +91,7 @@ void Instruction::execute() { // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec // std::cerr << "insn: " << metadata.mnemonic << " " << metadata.operandStr - // << std::endl; + // << ", group: " << getGroup() << std::endl; executed_ = true; switch (metadata.opcode) { @@ -943,9 +939,9 @@ void Instruction::execute() { case Opcode::RISCV_FLW: { // FLW rd,rs1,imm // Note: elements of memory data are RegisterValue's // Get as uint32 to allow for NaN boxing - const uint32_t memSingle = memoryData[0].get(); + const float memSingle = memoryData[0].get(); - results[0] = RegisterValue(NanBox(memSingle), 8); + results[0] = RegisterValue(NanBoxFloat(memSingle), 8); break; } From 33bd0bbb3682b78d9e939ae60e07ca09f63bfcc0 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Feb 2023 14:48:58 +0000 Subject: [PATCH 009/115] Add floating point instruction groups and correctly tag integer multiply and divides --- src/include/simeng/arch/riscv/Instruction.hh | 2 ++ .../simeng/arch/riscv/InstructionGroups.hh | 36 ++++++++++++++----- src/lib/ModelConfig.cc | 2 +- src/lib/arch/riscv/Instruction.cc | 6 +++- src/lib/arch/riscv/Instruction_decode.cc | 36 +++++++++++++++---- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 8b7a7d1a25..0470713e99 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -243,6 +243,8 @@ class Instruction : public simeng::Instruction { bool isCompare_ = false; /** Is this a floating point operation? */ bool isFloat_ = false; + /** Is this a floating point to integer convert operation? */ + bool isConvert_ = false; // Memory /** Set the accessed memory addresses, and create a corresponding memory data diff --git a/src/include/simeng/arch/riscv/InstructionGroups.hh b/src/include/simeng/arch/riscv/InstructionGroups.hh index 1a9b0342dc..a01877e34d 100644 --- a/src/include/simeng/arch/riscv/InstructionGroups.hh +++ b/src/include/simeng/arch/riscv/InstructionGroups.hh @@ -13,26 +13,46 @@ const uint16_t INT_SIMPLE_CMP = 3; const uint16_t INT_SIMPLE_LOGICAL = 4; const uint16_t INT_SIMPLE_SHIFT = 5; const uint16_t INT_MUL = 6; -const uint16_t INT_DIV = 7; +const uint16_t INT_DIV_OR_SQRT = 7; const uint16_t LOAD_INT = 8; const uint16_t STORE_INT = 9; -const uint16_t LOAD = 10; -const uint16_t STORE = 11; -const uint16_t BRANCH = 12; +const uint16_t FLOAT = 10; +const uint16_t FLOAT_SIMPLE = 11; +const uint16_t FLOAT_SIMPLE_ARTH = 12; +const uint16_t FLOAT_SIMPLE_CMP = 13; +const uint16_t FLOAT_SIMPLE_LOGICAL = 14; +const uint16_t FLOAT_SIMPLE_CVT = 15; +const uint16_t FLOAT_MUL = 16; +const uint16_t FLOAT_DIV_OR_SQRT = 17; +const uint16_t LOAD_FLOAT = 18; +const uint16_t STORE_FLOAT = 19; +const uint16_t LOAD = 20; +const uint16_t STORE = 21; +const uint16_t BRANCH = 22; } // namespace InstructionGroups -#define NUM_GROUPS 13 +#define NUM_GROUPS 23 const std::unordered_map> groupInheritance = { {InstructionGroups::INT, {InstructionGroups::INT_SIMPLE, InstructionGroups::INT_MUL, - InstructionGroups::INT_DIV}}, + InstructionGroups::INT_DIV_OR_SQRT}}, {InstructionGroups::INT_SIMPLE, {InstructionGroups::INT_SIMPLE_ARTH, InstructionGroups::INT_SIMPLE_CMP, InstructionGroups::INT_SIMPLE_LOGICAL, InstructionGroups::INT_SIMPLE_SHIFT}}, - {InstructionGroups::LOAD, {InstructionGroups::LOAD_INT}}, - {InstructionGroups::STORE, {InstructionGroups::STORE_INT}}}; + {InstructionGroups::LOAD, + {InstructionGroups::LOAD_INT, InstructionGroups::LOAD_FLOAT}}, + {InstructionGroups::STORE, + {InstructionGroups::STORE_INT, InstructionGroups::STORE_FLOAT}}, + {InstructionGroups::FLOAT, + {InstructionGroups::FLOAT_SIMPLE, InstructionGroups::FLOAT_MUL, + InstructionGroups::FLOAT_DIV_OR_SQRT}}, + {InstructionGroups::FLOAT_SIMPLE, + {InstructionGroups::FLOAT_SIMPLE_ARTH, + InstructionGroups::FLOAT_SIMPLE_LOGICAL, + InstructionGroups::FLOAT_SIMPLE_CMP, + InstructionGroups::FLOAT_SIMPLE_CVT}}}; } // namespace riscv } // namespace arch diff --git a/src/lib/ModelConfig.cc b/src/lib/ModelConfig.cc index 60117a8053..53dc83ac7c 100644 --- a/src/lib/ModelConfig.cc +++ b/src/lib/ModelConfig.cc @@ -715,7 +715,7 @@ void ModelConfig::createGroupMapping() { "INT_SIMPLE_LOGICAL", "INT_SIMPLE_SHIFT", "INT_MUL", - "INT_DIV", + "INT_DIV_OR_SQRT", "LOAD_INT", "STORE_INT", "LOAD", diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 686034650a..63c77efa7e 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -135,12 +135,16 @@ uint64_t Instruction::getKnownTarget() const { return knownTarget_; } uint16_t Instruction::getGroup() const { uint16_t base = InstructionGroups::INT; + if (isFloat()) { + base = InstructionGroups::FLOAT; + } + if (isBranch()) return InstructionGroups::BRANCH; if (isLoad()) return base + 8; if (isStoreAddress()) return base + 9; if (isDivide_) return base + 7; if (isMultiply_) return base + 6; - if (isShift_) return base + 5; + if (isShift_ || isConvert_) return base + 5; if (isLogical_) return base + 4; if (isCompare_) return base + 3; return base + 2; // Default return is {Data type}_SIMPLE_ARTH diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 2cf3e12c7c..1079b6db33 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -342,27 +342,45 @@ void Instruction::decode() { (Opcode::RISCV_OR <= metadata.opcode && metadata.opcode <= Opcode::RISCV_ORI) || (Opcode::RISCV_AND <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_ANDI)) { + metadata.opcode <= Opcode::RISCV_ANDI) || + (Opcode::RISCV_FSGNJN_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FSGNJ_S)) { // Logical instructions isLogical_ = true; } if ((Opcode::RISCV_SLT <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_SLTU)) { + metadata.opcode <= Opcode::RISCV_SLTU) || + (Opcode::RISCV_FEQ_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FEQ_S) || + (Opcode::RISCV_FLE_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FLT_S) || + (Opcode::RISCV_FMAX_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FMIN_S)) { // Compare instructions isCompare_ = true; } if ((Opcode::RISCV_MUL <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_MULW)) { + metadata.opcode <= Opcode::RISCV_MULW) || + (Opcode::RISCV_FMADD_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FMADD_S) || + (Opcode::RISCV_FMSUB_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FMUL_S) || + (Opcode::RISCV_FNMADD_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FNMSUB_S)) { // Compare instructions isMultiply_ = true; } - if (((Opcode::RISCV_REM <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_REMW) || - (Opcode::RISCV_DIV <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_DIVW))) { + if ((Opcode::RISCV_REM <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_REMW) || + (Opcode::RISCV_DIV <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_DIVW) || + (Opcode::RISCV_FDIV_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FDIV_S) || + (Opcode::RISCV_FSQRT_D <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_FSQRT_S)) { // Compare instructions isDivide_ = true; } @@ -373,6 +391,10 @@ void Instruction::decode() { metadata.opcode <= Opcode::RISCV_FSW)) { // Floating point operation isFloat_ = true; + if ((metadata.opcode >= Opcode::RISCV_FCVT_D_L && + metadata.opcode <= Opcode::RISCV_FCVT_W_S)) { + isConvert_ = true; + } } // Set branch type From 8fccee89829d63ec7cc219a3e303f422007796eb Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Feb 2023 11:23:27 +0000 Subject: [PATCH 010/115] Correctly tag RISC-V divide and multiply instructions --- src/lib/arch/riscv/Instruction_decode.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 6db263796b..df7afef528 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -239,6 +239,20 @@ void Instruction::decode() { isCompare_ = true; } + if ((Opcode::RISCV_MUL <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_MULW)) { + // Compare instructions + isMultiply_ = true; + } + + if (((Opcode::RISCV_REM <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_REMW) || + (Opcode::RISCV_DIV <= metadata.opcode && + metadata.opcode <= Opcode::RISCV_DIVW))) { + // Compare instructions + isDivide_ = true; + } + // Set branch type switch (metadata.opcode) { case Opcode::RISCV_BEQ: From 8fe9969a5d47a5699dfa11d7d5b6d85ef47a95a0 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Feb 2023 17:05:32 +0000 Subject: [PATCH 011/115] Create test reproducing error most of the time --- test/regression/riscv/CMakeLists.txt | 1 + test/regression/riscv/InorderPipeline.cc | 34 ++++++++++++++++++++ test/regression/riscv/RISCVRegressionTest.hh | 5 +-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/regression/riscv/InorderPipeline.cc diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index 1821d7ab5f..24050bfa48 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -2,6 +2,7 @@ add_executable(regression-riscv RISCVRegressionTest.cc RISCVRegressionTest.hh LoadStoreQueue.cc + InorderPipeline.cc SmokeTest.cc Syscall.cc instructions/arithmetic.cc diff --git a/test/regression/riscv/InorderPipeline.cc b/test/regression/riscv/InorderPipeline.cc new file mode 100644 index 0000000000..dfc56e4496 --- /dev/null +++ b/test/regression/riscv/InorderPipeline.cc @@ -0,0 +1,34 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using inorderPipeline = RISCVRegressionTest; + +TEST_P(inorderPipeline, halt) { + RUN_RISCV(R"( + li a1, 2 + li a2, 1 + li a4, 5 + + beq a1, a2, end # mispredict with target out of programByteLength creates pipeline bubble + div a3, a1, a2 # multicycle instruction ties up execution unit causing decode to halt and next instruction to be stuck in the tail of pipelined buffer + beq a1, a2, end # mispredict with target out of programByteLength halts fetch unit + # this only occurs because the instruction address is set after decode + # therefor a garbage value is used sometimes causing the halt at ~FetchUnit.cc::177 + + # This sequence of instructions with this inorder pipeline causes all + # buffers to appear empty and the fetch unit to halt causing the inorder + # core to halt early which is incorrect behaviour. This is fixed in PR TODO + + li a4, 10 # Occurs if core does not halt + end: + )"); + EXPECT_EQ(getGeneralRegister(14), 10); +} + +INSTANTIATE_TEST_SUITE_P(RISCV, inorderPipeline, + ::testing::Values(std::make_tuple(INORDER, + YAML::Load("{}"))), + paramToString); + +} // namespace diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 29ce769783..2dca8b073e 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -13,14 +13,15 @@ "FrontEnd: 4, LSQ-Completion: 2}, Queue-Sizes: {ROB: 180, Load: 64, " \ "Store: 36}, Branch-Predictor: {BTB-Tag-Bits: 11, Saturating-Count-Bits: " \ "2, Global-History-Length: 10, RAS-entries: 5, Fallback-Static-Predictor: " \ - "0}, L1-Data-Memory: {Interface-Type: Fixed}, L1-Instruction-Memory: " \ + "2}, L1-Data-Memory: {Interface-Type: Fixed}, L1-Instruction-Memory: " \ "{Interface-Type: Flat}, LSQ-L1-Interface: {Access-Latency: 4, Exclusive: " \ "False, Load-Bandwidth: 32, Store-Bandwidth: 16, " \ "Permitted-Requests-Per-Cycle: 2, Permitted-Loads-Per-Cycle: 2, " \ "Permitted-Stores-Per-Cycle: 1}, Ports: {'0': {Portname: Port 0, " \ "Instruction-Group-Support: [0, 10, 11, 12 ]}}, Reservation-Stations: " \ "{'0': {Size: 60, Dispatch-Rate: 4, Ports: [0]}}, Execution-Units: " \ - "{'0': {Pipelined: true}}}") + "{'0': {Pipelined: true}}, Latencies: {'0': {Instruction-Group: {0: '7'}, " \ + "Execution-Latency: 39, Execution-Throughput: 39}}}") /** A helper function to convert the supplied parameters of * INSTANTIATE_TEST_SUITE_P into test name. */ From ab352c3e0103772775d107fc8bafb2da1f4f2238 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 28 Feb 2023 12:23:58 +0000 Subject: [PATCH 012/115] Update inorder halting condition --- src/include/simeng/pipeline/ExecuteUnit.hh | 4 +++ src/lib/models/inorder/Core.cc | 38 +++++++++++++++------- src/lib/pipeline/ExecuteUnit.cc | 3 ++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/include/simeng/pipeline/ExecuteUnit.hh b/src/include/simeng/pipeline/ExecuteUnit.hh index e95391a8f2..b7d3d7cabb 100644 --- a/src/include/simeng/pipeline/ExecuteUnit.hh +++ b/src/include/simeng/pipeline/ExecuteUnit.hh @@ -65,6 +65,8 @@ class ExecuteUnit { /** Retrieve the number of active execution cycles. */ uint64_t getCycles() const; + bool isEmpty() const; + private: /** Execute the supplied uop, write it into the output buffer, and forward * results back to dispatch/issue. */ @@ -133,6 +135,8 @@ class ExecuteUnit { /** The number of active execution cycles that were observed. */ uint64_t cycles_ = 0; + + bool empty_ = true; }; } // namespace pipeline diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index a9604bc085..9c7c388e9d 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -71,9 +71,8 @@ void Core::tick() { // as these will now loop around and become the tail. fetchToDecodeBuffer_.tick(); decodeToExecuteBuffer_.tick(); - for (auto& buffer : completionSlots_) { - buffer.tick(); - } + // Only ever 1 completion slot + completionSlots_[0].tick(); if (exceptionGenerated_) { handleException(); @@ -116,14 +115,31 @@ bool Core::hasHalted() const { } // Core is considered to have halted when the fetch unit has halted, there - // are no uops at the head of any buffer, and no exception is currently being - // handled. - bool decodePending = fetchToDecodeBuffer_.getHeadSlots()[0].size() > 0; - bool executePending = decodeToExecuteBuffer_.getHeadSlots()[0] != nullptr; - bool writebackPending = completionSlots_[0].getHeadSlots()[0] != nullptr; + // are no uops pending in any buffer, the execute unit is not currently + // processing an instructions and no exception is currently being handled. + + // Units place uops in buffer tail, but if buffer is stalled, uops do not + // move to head slots and so remain in tail slots. Buffer head appears + // empty. Check emptiness accordingly + auto decSlots = fetchToDecodeBuffer_.isStalled() + ? fetchToDecodeBuffer_.getTailSlots()[0] + : fetchToDecodeBuffer_.getHeadSlots()[0]; + bool decodePending = decSlots.size() > 0; + + auto exeSlots = decodeToExecuteBuffer_.isStalled() + ? decodeToExecuteBuffer_.getTailSlots()[0] + : decodeToExecuteBuffer_.getHeadSlots()[0]; + bool executePending = exeSlots != nullptr; + + auto writeSlots = completionSlots_[0].isStalled() + ? completionSlots_[0].getTailSlots()[0] + : completionSlots_[0].getHeadSlots()[0]; + + bool writebackPending = writeSlots != nullptr; return (fetchUnit_.hasHalted() && !decodePending && !writebackPending && - !executePending && exceptionHandler_ == nullptr); + !executePending && executeUnit_.isEmpty() && + exceptionHandler_ == nullptr); } const ArchitecturalRegisterFileSet& Core::getArchitecturalRegisterFileSet() @@ -220,8 +236,8 @@ void Core::loadData(const std::shared_ptr& instruction) { dataMemory_.requestRead(target); } - // NOTE: This model only supports zero-cycle data memory models, and will not - // work unless data requests are handled synchronously. + // NOTE: This model only supports zero-cycle data memory models, and will + // not work unless data requests are handled synchronously. for (const auto& response : dataMemory_.getCompletedReads()) { instruction->supplyData(response.target.address, response.data); } diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index 83a71c5b1a..3df15eaf2b 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -28,6 +28,7 @@ ExecuteUnit::ExecuteUnit( void ExecuteUnit::tick() { tickCounter_++; shouldFlush_ = false; + empty_ = false; if (stallUntil_ <= tickCounter_) { input_.stall(false); @@ -161,6 +162,7 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { forwardOperands_(uop->getDestinationRegisters(), uop->getResults()); output_.getTailSlots()[0] = std::move(uop); + empty_ = true; } bool ExecuteUnit::shouldFlush() const { return shouldFlush_; } @@ -223,6 +225,7 @@ uint64_t ExecuteUnit::getBranchMispredictedCount() const { } uint64_t ExecuteUnit::getCycles() const { return cycles_; } +bool ExecuteUnit::isEmpty() const { return empty_; } } // namespace pipeline } // namespace simeng From 67fab7c35bc4a26fdefe6b15c5caae80514cc212 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 28 Feb 2023 15:24:50 +0000 Subject: [PATCH 013/115] Rename knownTarget_ to knownOffset_ to better reflect meaning. Update RISC-V implementation --- src/include/simeng/Instruction.hh | 2 +- src/lib/arch/aarch64/Instruction.cc | 2 +- src/lib/arch/aarch64/Instruction_decode.cc | 10 +++++----- src/lib/arch/riscv/Instruction.cc | 2 +- src/lib/arch/riscv/Instruction_decode.cc | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/include/simeng/Instruction.hh b/src/include/simeng/Instruction.hh index 8b1cf2f9db..a93526e837 100644 --- a/src/include/simeng/Instruction.hh +++ b/src/include/simeng/Instruction.hh @@ -209,7 +209,7 @@ class Instruction { BranchType branchType_ = BranchType::Unknown; /** If the branch target is known at the time of decode, store it. */ - uint64_t knownTarget_ = 0; + uint64_t knownOffset_ = 0; // Flushing /** This instruction's sequence ID; a higher ID represents a chronologically diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index b6884443c0..568e8592fe 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -130,7 +130,7 @@ std::tuple Instruction::checkEarlyBranchMisprediction() const { BranchType Instruction::getBranchType() const { return branchType_; } -uint64_t Instruction::getKnownTarget() const { return knownTarget_; } +uint64_t Instruction::getKnownTarget() const { return knownOffset_; } uint16_t Instruction::getGroup() const { // Use identifiers to decide instruction group diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 4237475f52..3c0a4dfee3 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -368,7 +368,7 @@ void Instruction::decode() { switch (metadata.opcode) { case Opcode::AArch64_B: // b label branchType_ = BranchType::Unconditional; - knownTarget_ = metadata.operands[0].imm; + knownOffset_ = metadata.operands[0].imm; break; case Opcode::AArch64_BR: { // br xn branchType_ = BranchType::Unconditional; @@ -376,7 +376,7 @@ void Instruction::decode() { } case Opcode::AArch64_BL: // bl #imm branchType_ = BranchType::SubroutineCall; - knownTarget_ = metadata.operands[0].imm; + knownOffset_ = metadata.operands[0].imm; break; case Opcode::AArch64_BLR: { // blr xn branchType_ = BranchType::SubroutineCall; @@ -387,7 +387,7 @@ void Instruction::decode() { branchType_ = BranchType::LoopClosing; else branchType_ = BranchType::Conditional; - knownTarget_ = metadata.operands[0].imm; + knownOffset_ = metadata.operands[0].imm; break; } case Opcode::AArch64_CBNZW: // cbnz wn, #imm @@ -401,7 +401,7 @@ void Instruction::decode() { branchType_ = BranchType::LoopClosing; else branchType_ = BranchType::Conditional; - knownTarget_ = metadata.operands[1].imm; + knownOffset_ = metadata.operands[1].imm; break; } case Opcode::AArch64_TBNZW: // tbnz wn, #imm, label @@ -415,7 +415,7 @@ void Instruction::decode() { branchType_ = BranchType::LoopClosing; else branchType_ = BranchType::Conditional; - knownTarget_ = metadata.operands[2].imm; + knownOffset_ = metadata.operands[2].imm; break; } case Opcode::AArch64_RET: { // ret {xr} diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 530890e9a6..0c0b866f9e 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -129,7 +129,7 @@ std::tuple Instruction::checkEarlyBranchMisprediction() const { BranchType Instruction::getBranchType() const { return branchType_; } -uint64_t Instruction::getKnownTarget() const { return knownTarget_; } +uint64_t Instruction::getKnownTarget() const { return knownOffset_; } uint16_t Instruction::getGroup() const { uint16_t base = InstructionGroups::INT; diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index df7afef528..9b42705164 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -262,12 +262,12 @@ void Instruction::decode() { case Opcode::RISCV_BGE: case Opcode::RISCV_BGEU: branchType_ = BranchType::Conditional; - knownTarget_ = instructionAddress_ + metadata.operands[2].imm; + knownOffset_ = metadata.operands[2].imm; break; case Opcode::RISCV_JAL: case Opcode::RISCV_JALR: branchType_ = BranchType::Unconditional; - knownTarget_ = instructionAddress_ + metadata.operands[1].imm; + knownOffset_ = metadata.operands[1].imm; break; } } From 9230d43f50c22aa7361977fab965ac0eae731ba0 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 28 Feb 2023 16:26:10 +0000 Subject: [PATCH 014/115] Update comments --- src/lib/arch/riscv/Instruction_decode.cc | 4 ++-- test/regression/riscv/InorderPipeline.cc | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 9b42705164..a058a2bfe9 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -241,7 +241,7 @@ void Instruction::decode() { if ((Opcode::RISCV_MUL <= metadata.opcode && metadata.opcode <= Opcode::RISCV_MULW)) { - // Compare instructions + // Multiply instructions isMultiply_ = true; } @@ -249,7 +249,7 @@ void Instruction::decode() { metadata.opcode <= Opcode::RISCV_REMW) || (Opcode::RISCV_DIV <= metadata.opcode && metadata.opcode <= Opcode::RISCV_DIVW))) { - // Compare instructions + // Divide instructions isDivide_ = true; } diff --git a/test/regression/riscv/InorderPipeline.cc b/test/regression/riscv/InorderPipeline.cc index dfc56e4496..20144eac6e 100644 --- a/test/regression/riscv/InorderPipeline.cc +++ b/test/regression/riscv/InorderPipeline.cc @@ -10,15 +10,19 @@ TEST_P(inorderPipeline, halt) { li a2, 1 li a4, 5 - beq a1, a2, end # mispredict with target out of programByteLength creates pipeline bubble - div a3, a1, a2 # multicycle instruction ties up execution unit causing decode to halt and next instruction to be stuck in the tail of pipelined buffer - beq a1, a2, end # mispredict with target out of programByteLength halts fetch unit - # this only occurs because the instruction address is set after decode - # therefor a garbage value is used sometimes causing the halt at ~FetchUnit.cc::177 + beq a1, a2, end # mispredict with target out of programByteLength creates + # pipeline bubble + div a3, a1, a2 # multicycle instruction ties up execution unit causing + # decode to halt and next instruction to be stuck in the + # tail of pipelined buffer + beq a1, a2, end # mispredict with target out of programByteLength halts + # fetch unit this only occurs because the instruction + # address is set after decode therefor a garbage value is + # used sometimes causing the halt at ~FetchUnit.cc::177 # This sequence of instructions with this inorder pipeline causes all # buffers to appear empty and the fetch unit to halt causing the inorder - # core to halt early which is incorrect behaviour. This is fixed in PR TODO + # core to halt early which is incorrect behaviour. This is fixed in PR 294 li a4, 10 # Occurs if core does not halt end: From 5100faa2211f42e65748fd1262e2a00f948c9a7a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 23 Feb 2023 13:49:00 +0000 Subject: [PATCH 015/115] Update config file to test programs [WIP] --- configs/DEMO_RISCV.yaml | 38 +++++++++++++++++------ src/lib/ModelConfig.cc | 10 ++++++ src/lib/arch/riscv/Architecture.cc | 3 ++ src/lib/arch/riscv/ExceptionHandler.cc | 5 ++- src/lib/arch/riscv/InstructionMetadata.cc | 15 ++++++--- src/lib/arch/riscv/Instruction_decode.cc | 8 +++-- test/regression/riscv/instructions/csr.cc | 10 +++--- 7 files changed, 67 insertions(+), 22 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 381b6fd70e..87a2059ccb 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -5,13 +5,14 @@ Core: ISA: rv64 - Simulation-Mode: emulation + Simulation-Mode: inorderpipelined Clock-Frequency: 2.5 - Fetch-Block-Size: 32 + # Timer-Frequency is in MHz. + Timer-Frequency: 200 Fetch: Fetch-Block-Size: 32 - Loop-Buffer-Size: 0 - Loop-Detection-Threshold: 0 + Loop-Buffer-Size: 64 + Loop-Detection-Threshold: 4 Process-Image: Heap-Size: 1073741824 Stack-Size: 1048576 @@ -20,7 +21,6 @@ Register-Set: FloatingPoint-Count: 90 Pipeline-Widths: Commit: 4 - Dispatch-Rate: 4 FrontEnd: 4 LSQ-Completion: 2 Queue-Sizes: @@ -31,10 +31,8 @@ Branch-Predictor: BTB-Tag-Bits: 11 Saturating-Count-Bits: 2 Global-History-Length: 10 - RAS-entries: 1 + RAS-entries: 5 Fallback-Static-Predictor: "Always-Taken" - Branch-Predictor: - BTB-bitlength: 16 L1-Data-Memory: Interface-Type: Flat L1-Instruction-Memory: @@ -53,10 +51,12 @@ Ports: Instruction-Support: - INT_SIMPLE - INT_MUL + - FLOAT 1: Portname: Port 1 Instruction-Support: - INT + - FLOAT 2: Portname: Port 2 Instruction-Support: @@ -113,9 +113,29 @@ Latencies: Execution-Throughput: 1 2: Instruction-Groups: - - INT_DIV + - INT_DIV_OR_SQRT Execution-Latency: 39 Execution-Throughput: 39 + 3: + Instruction-Groups: + - FLOAT_SIMPLE_CMP + Execution-Latency: 5 + Execution-Throughput: 1 + 4: + Instruction-Groups: + - FLOAT_MUL + Execution-Latency: 6 + Execution-Throughput: 1 + 5: + Instruction-Groups: + - FLOAT_SIMPLE_CVT + Execution-Latency: 7 + Execution-Throughput: 1 + 6: + Instruction-Groups: + - FLOAT_DIV_OR_SQRT + Execution-Latency: 16 + Execution-Throughput: 16 # CPU-Info mainly used to generate a replica of the special (or system) file directory # structure CPU-Info: diff --git a/src/lib/ModelConfig.cc b/src/lib/ModelConfig.cc index 53dc83ac7c..38a1da9e8b 100644 --- a/src/lib/ModelConfig.cc +++ b/src/lib/ModelConfig.cc @@ -718,6 +718,16 @@ void ModelConfig::createGroupMapping() { "INT_DIV_OR_SQRT", "LOAD_INT", "STORE_INT", + "FLOAT", + "FLOAT_SIMPLE", + "FLOAT_SIMPLE_ARTH", + "FLOAT_SIMPLE_CMP", + "FLOAT_SIMPLE_LOGICAL", + "FLOAT_SIMPLE_CVT", + "FLOAT_MUL", + "FLOAT_DIV_OR_SQRT", + "LOAD_FLOAT", + "STORE_FLOAT", "LOAD", "STORE", "BRANCH"}; diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 9f408d27fc..8adc7e571f 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -105,6 +105,9 @@ Architecture::Architecture(kernel::Linux& kernel, YAML::Node config) for (size_t j = 0; j < group_node.size(); j++) { uint16_t group = group_node[j].as(); uint8_t newPort = static_cast(i); + // std::cerr << "group: " << group << " port: " << (int)newPort + // << std::endl; + groupExecutionInfo_[group].ports.push_back(newPort); // Add inherited support for those appropriate groups std::queue groups; diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index b68a0cf410..ef8bd1bab7 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -659,7 +659,10 @@ bool ExceptionHandler::init() { stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; } - + case 1024: { + std::cout << "SIMENG: BROKEN SYSCALL 1024" << std::endl; + break; + } default: printException(instruction_); std::cout << "\n[SimEng:ExceptionHandler] Unrecognised syscall: " diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index f7fc991811..78527f17e5 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -307,6 +307,17 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { RISCV_OP_IMM; // TODO needs to become reg when CS updated operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + operandCount = 3; + } else if (operandCount == 2 && strcmp(mnemonic, "fsflags") == 0) { + // fsflags R1, R2 is pseudo of CSRRW r1, fflags, rs (Write FP exception + // flags) + // CSRRW R1, R2, _ -> CSRRW R1, fflags, R2 + operands[2] = operands[1]; + + operands[1].type = + RISCV_OP_IMM; // TODO needs to become reg when CS updated + operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + operandCount = 3; } else if (strcmp(mnemonic, "csrw") == 0) { assert(false && "Unimplemented psuedoinstruction csrw"); @@ -330,10 +341,6 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operandCount = 3; } else if (strcmp(mnemonic, "fsrm") == 0) { assert(false && "Unimplemented psuedoinstruction fsrm"); - } else if (strcmp(mnemonic, "fsflags") == 0) { - assert(false && "Unimplemented psuedoinstruction fsflags"); - } else if (strcmp(mnemonic, "fsflags") == 0) { - assert(false && "Unimplemented psuedoinstruction fsflags"); } break; } diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 1079b6db33..556cde37a0 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -240,9 +240,11 @@ void Instruction::decode() { } if ((Opcode::RISCV_AMOADD_D <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_AMOXOR_W_RL) || - (Opcode::RISCV_CSRRC <= metadata.opcode && - metadata.opcode <= Opcode::RISCV_CSRRWI)) { + metadata.opcode <= Opcode::RISCV_AMOXOR_W_RL) + // || + // (Opcode::RISCV_CSRRC <= metadata.opcode && + // metadata.opcode <= Opcode::RISCV_CSRRWI) + ) { // Atomics: both load and store isLoad_ = true; isStore_ = true; diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index 94c0d76f6b..b9425cb7df 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -4,11 +4,11 @@ namespace { using InstCsr = RISCVRegressionTest; -TEST_P(InstCsr, jalr) { - RUN_RISCV(R"( - csrrw t1, cycle, t1 - )"); -} +// TEST_P(InstCsr, jalr) { +// RUN_RISCV(R"( +// csrrw t1, cycle, t1 +// )"); +// } INSTANTIATE_TEST_SUITE_P(RISCV, InstCsr, ::testing::Values(std::make_tuple(EMULATION, From f04232c440cec39bd3374a0809a31afe26e2e56b Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 28 Feb 2023 17:06:04 +0000 Subject: [PATCH 016/115] Update RISCV_CONFIG to use new instruction groups --- src/lib/arch/riscv/Instruction_decode.cc | 4 ++-- test/regression/riscv/RISCVRegressionTest.hh | 2 +- test/regression/riscv/instructions/csr.cc | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 8ef2e33afc..c9177b7c50 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -165,8 +165,8 @@ void Instruction::invalidateIfNotImplemented() { // if (metadata.opcode == Opcode::RISCV_FLE_D) return; // if (metadata.opcode == Opcode::RISCV_FLE_S) return; - std::cout << "[SimEng:RISC-V:Decode] Insn: " << metadata.mnemonic << " " - << metadata.operandStr << std::endl; + // std::cout << "[SimEng:RISC-V:Decode] Insn: " << metadata.mnemonic << " " + // << metadata.operandStr << std::endl; exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index a55ca6679c..d0812eb05f 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -18,7 +18,7 @@ "False, Load-Bandwidth: 32, Store-Bandwidth: 16, " \ "Permitted-Requests-Per-Cycle: 2, Permitted-Loads-Per-Cycle: 2, " \ "Permitted-Stores-Per-Cycle: 1}, Ports: {'0': {Portname: Port 0, " \ - "Instruction-Group-Support: [0, 10, 11, 12 ]}}, Reservation-Stations: " \ + "Instruction-Group-Support: [0, 10, 20, 21, 22 ]}}, Reservation-Stations: " \ "{'0': {Size: 60, Dispatch-Rate: 4, Ports: [0]}}, Execution-Units: " \ "{'0': {Pipelined: true}}, Latencies: {'0': {Instruction-Group: {0: '7'}, " \ "Execution-Latency: 39, Execution-Throughput: 39}}}") diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index b9425cb7df..72a2d9a602 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -4,11 +4,11 @@ namespace { using InstCsr = RISCVRegressionTest; -// TEST_P(InstCsr, jalr) { -// RUN_RISCV(R"( -// csrrw t1, cycle, t1 -// )"); -// } +TEST_P(InstCsr, jalr) { + RUN_RISCV(R"( + #csrrw t1, cycle, t1 + )"); +} INSTANTIATE_TEST_SUITE_P(RISCV, InstCsr, ::testing::Values(std::make_tuple(EMULATION, From 78ffa82ef3a8c6e4a07f371975d7ee0c64806d12 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Mar 2023 10:26:50 +0000 Subject: [PATCH 017/115] Minor updates --- CMakeLists.txt | 2 +- src/lib/arch/riscv/Instruction_execute.cc | 10 ++++------ test/regression/riscv/RISCVRegressionTest.hh | 6 +++--- test/regression/riscv/instructions/float.cc | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccbc9074a0..f08650c10a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ FetchContent_MakeAvailable_Args(yaml-cpp EXCLUDE_FROM_ALL) option(SIMENG_ENABLE_TESTS "Whether to enable testing for SimEng" OFF) option(SIMENG_USE_EXTERNAL_LLVM "Use an external LLVM rather than building it as a submodule" OFF) option(SIMENG_SANITIZE "Enable compiler sanitizers" OFF) -option(SIMENG_OPTIMIZE "Enable Extra Compiler Optimizatoins" OFF) +option(SIMENG_OPTIMIZE "Enable Extra Compiler Optimizations" OFF) option(SIMENG_ENABLE_SST "Compile SimEng SST Wrapper" OFF) option(SIMENG_ENABLE_SST_TESTS "Enable testing for SST" OFF) diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index d909899b4c..7ee7d30432 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -90,9 +90,6 @@ void Instruction::execute() { // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec - // std::cerr << "insn: " << metadata.mnemonic << " " << metadata.operandStr - // << ", group: " << getGroup() << std::endl; - executed_ = true; switch (metadata.opcode) { case Opcode::RISCV_LB: { // LB rd,rs1,imm @@ -126,7 +123,7 @@ void Instruction::execute() { } case Opcode::RISCV_LD: { // LD rd,rs1,imm // Note: elements of memory data are RegisterValue's - results[0] = memoryData[0]; + results[0] = RegisterValue(memoryData[0].get(), 8); break; } case Opcode::RISCV_SB: // SB rs1,rs2,imm @@ -884,8 +881,9 @@ void Instruction::execute() { break; } } else { - std::cerr << "[SimEng:RISC-V:Execute] Unknown system register" - << std::endl; + // std::cerr << "[SimEng:RISC-V:Execute] Unknown system register: + // " + // << metadata.operands[1].reg << std::endl; } break; } diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index d0812eb05f..d625614016 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -18,9 +18,9 @@ "False, Load-Bandwidth: 32, Store-Bandwidth: 16, " \ "Permitted-Requests-Per-Cycle: 2, Permitted-Loads-Per-Cycle: 2, " \ "Permitted-Stores-Per-Cycle: 1}, Ports: {'0': {Portname: Port 0, " \ - "Instruction-Group-Support: [0, 10, 20, 21, 22 ]}}, Reservation-Stations: " \ - "{'0': {Size: 60, Dispatch-Rate: 4, Ports: [0]}}, Execution-Units: " \ - "{'0': {Pipelined: true}}, Latencies: {'0': {Instruction-Group: {0: '7'}, " \ + "Instruction-Group-Support: [0, 10, 20, 21, 22]}}, Reservation-Stations: " \ + "{'0': {Size: 60, Dispatch-Rate: 4, Ports: [0]}}, Execution-Units: {'0': " \ + "{Pipelined: true}}, Latencies: {'0': {Instruction-Group: {0: '7'}, " \ "Execution-Latency: 39, Execution-Throughput: 39}}}") /** A helper function to convert the supplied parameters of diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc index 778678095f..0e5964eac0 100644 --- a/test/regression/riscv/instructions/float.cc +++ b/test/regression/riscv/instructions/float.cc @@ -565,7 +565,7 @@ TEST_P(InstFloat, FCVT_WU_D) { fcvt.wu.d t3, fa3, rtz # should convert to 4 fcvt.wu.d t1, fa4 # should convert to 0 fcvt.wu.d t4, fa4, rtz # should convert to 0 - fcvt.wu.d t2, fa6 #Nan converts to 0x7fffffff in integer reg + fcvt.wu.d t2, fa6 #Nan converts to 0xffffffffffffffff in integer reg fcvt.wu.d t5, fa5 )"); From 685957cf4695aa664de36573d7189025e875d3e2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Mar 2023 11:25:55 +0000 Subject: [PATCH 018/115] Populate auxved with PHDR values --- src/include/simeng/Elf.hh | 22 ++++--- src/include/simeng/kernel/LinuxProcess.hh | 33 ++++++++++ src/lib/Elf.cc | 74 ++++++++++++++--------- src/lib/kernel/LinuxProcess.cc | 15 ++++- 4 files changed, 106 insertions(+), 38 deletions(-) diff --git a/src/include/simeng/Elf.hh b/src/include/simeng/Elf.hh index 88e419e6a5..0d41ba7aac 100644 --- a/src/include/simeng/Elf.hh +++ b/src/include/simeng/Elf.hh @@ -12,13 +12,13 @@ const char Format32 = 1; const char Format64 = 2; } // namespace ElfBitFormat -struct ElfHeader { - uint32_t type; - uint64_t offset; - uint64_t virtualAddress; - uint64_t physicalAddress; - uint64_t fileSize; - uint64_t memorySize; +struct Elf64_Phdr { + uint32_t p_type; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; }; /** A processed Executable and Linkable Format (ELF) file. */ @@ -29,10 +29,16 @@ class Elf { uint64_t getProcessImageSize() const; bool isValid() const; uint64_t getEntryPoint() const; + uint64_t getPhdrTableAddress() const; + uint64_t getPHENT() const; + uint64_t getPHNUM() const; private: uint64_t entryPoint_; - std::vector headers_; + std::vector pheaders_; + uint16_t e_phentsize; + uint16_t e_phnum; + uint64_t phdrTableAddress_ = 0; bool isValid_ = false; uint64_t processImageSize_; }; diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index 9796b52937..6dffbf0392 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -8,6 +8,30 @@ namespace simeng { namespace kernel { +namespace auxVec { +/** Labels for the entries in the auxiliary vector. */ +enum labels { + AT_NULL = 0, /* end of vector */ + AT_IGNORE = 1, /* entry should be ignored */ + AT_EXECFD = 2, /* file descriptor of program */ + AT_PHDR = 3, /* program headers for program */ + AT_PHENT = 4, /* size of program header entry */ + AT_PHNUM = 5, /* number of program headers */ + AT_PAGESZ = 6, /* system page size */ + AT_BASE = 7, /* base address of interpreter */ + AT_FLAGS = 8, /* flags */ + AT_ENTRY = 9, /* entry point of program */ + AT_NOTELF = 10, /* program is not ELF */ + AT_UID = 11, /* real uid */ + AT_EUID = 12, /* effective uid */ + AT_GID = 13, /* real gid */ + AT_EGID = 14, /* effective gid */ + AT_PLATFORM = 15, /* string identifying CPU for optimizations */ + AT_HWCAP = 16, /* arch dependent hints at CPU capabilities */ + AT_CLKTCK = 17 /* frequency at which times() increments */ +}; +} // namespace auxVec + /** Align `address` to an `alignTo`-byte boundary by rounding up to the nearest * multiple. */ uint64_t alignToBoundary(uint64_t value, uint64_t boundary); @@ -90,6 +114,15 @@ class LinuxProcess { /** The entry point of the process. */ uint64_t entryPoint_ = 0; + /** Program header table address */ + uint64_t phdrTableAddress_; + + /** Number of program headers */ + uint64_t phnum_; + + /** Size of program header entry */ + uint64_t phent_; + /** The address of the start of the heap region. */ uint64_t heapStart_; diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 6654cc86a8..027e0503e0 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -2,6 +2,7 @@ #include #include +#include namespace simeng { @@ -36,6 +37,7 @@ Elf::Elf(std::string path, char** imagePointer) { char fileMagic[4]; file.read(fileMagic, 4); if (std::memcmp(elfMagic, fileMagic, sizeof(elfMagic))) { + std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; return; } @@ -48,6 +50,8 @@ Elf::Elf(std::string path, char** imagePointer) { char bitFormat; file.read(&bitFormat, sizeof(bitFormat)); if (bitFormat != ElfBitFormat::Format64) { + std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" + << std::endl; return; } @@ -73,37 +77,36 @@ Elf::Elf(std::string path, char** imagePointer) { */ // Seek to the byte representing the start of the header offset table. - uint64_t headerOffset; - file.read(reinterpret_cast(&headerOffset), sizeof(headerOffset)); + uint64_t e_phoff; + file.read(reinterpret_cast(&e_phoff), sizeof(e_phoff)); /** - * Starting 54th byte of the ELF Header a 16-bit value indicates - * the size of each entry in the ELF Program header. In the `elf64_hdr` - * struct this value maps to the member `Elf64_Half e_phentsize`. All - * header entries have the same size. + * Starting from the 54th byte of the ELF Header a 16-bit value indicates + * the the size in bytes of one entry in the + * file's program header table; all entries are the same + * size. In the `elf64_hdr` + * struct this value maps to the member `Elf64_Half e_phentsize`. * Starting from the 56th byte a 16-bit value represents the number - * of header entries in the ELF Program header. In the `elf64_hdr` + * of program header entries in the ELF Program header. In the `elf64_hdr` * struct this value maps to `Elf64_Half e_phnum`. */ // Seek to the byte representing header entry size. file.seekg(0x36); - uint16_t headerEntrySize; - file.read(reinterpret_cast(&headerEntrySize), sizeof(headerEntrySize)); - uint16_t headerEntries; - file.read(reinterpret_cast(&headerEntries), sizeof(headerEntries)); + file.read(reinterpret_cast(&e_phentsize), sizeof(e_phentsize)); + file.read(reinterpret_cast(&e_phnum), sizeof(e_phnum)); // Resize the header to equal the number of header entries. - headers_.resize(headerEntries); + pheaders_.resize(e_phnum); processImageSize_ = 0; // Loop over all headers and extract them. - for (size_t i = 0; i < headerEntries; i++) { + for (size_t i = 0; i < e_phnum; i++) { // Since all headers entries have the same size. // We can extract the nth header using the header offset // and header entry size. - file.seekg(headerOffset + (i * headerEntrySize)); - auto& header = headers_[i]; + file.seekg(e_phoff + (i * e_phentsize)); + auto& header = pheaders_[i]; /** * Like the ELF Header, the ELF Program header is also defined @@ -133,22 +136,29 @@ Elf::Elf(std::string path, char** imagePointer) { // Each address-related field is 8 bytes in a 64-bit ELF file const int fieldBytes = 8; - file.read(reinterpret_cast(&(header.type)), sizeof(header.type)); + file.read(reinterpret_cast(&(header.p_type)), sizeof(header.p_type)); file.seekg(4, std::ios::cur); // Skip flags - file.read(reinterpret_cast(&(header.offset)), fieldBytes); - file.read(reinterpret_cast(&(header.virtualAddress)), fieldBytes); - file.read(reinterpret_cast(&(header.physicalAddress)), fieldBytes); - file.read(reinterpret_cast(&(header.fileSize)), fieldBytes); - file.read(reinterpret_cast(&(header.memorySize)), fieldBytes); + file.read(reinterpret_cast(&(header.p_offset)), fieldBytes); + file.read(reinterpret_cast(&(header.p_vaddr)), fieldBytes); + file.read(reinterpret_cast(&(header.p_paddr)), fieldBytes); + file.read(reinterpret_cast(&(header.p_filesz)), fieldBytes); + file.read(reinterpret_cast(&(header.p_memsz)), fieldBytes); + // Skip p_align // To construct the process we look for the largest virtual address and // add it to the memory size of the header. This way we obtain a very // large array which can hold data at large virtual address. // However, this way we end up creating a sparse array, in which most - // of the entries are unused. Also SimEng internally treats these + // of the entries are unused. Also, SimEng internally treats these // virtual address as physical addresses to index into this large array. - if (header.virtualAddress + header.memorySize > processImageSize_) { - processImageSize_ = header.virtualAddress + header.memorySize; + if (header.p_vaddr + header.p_memsz > processImageSize_) { + processImageSize_ = header.p_vaddr + header.p_memsz; + } + + // Find the table address used to populate the auxvec + if (header.p_offset <= e_phoff && + e_phoff < header.p_offset + header.p_filesz) { + phdrTableAddress_ = header.p_vaddr + (e_phoff - header.p_offset); } } @@ -162,12 +172,12 @@ Elf::Elf(std::string path, char** imagePointer) { */ // Process headers; only observe LOAD sections for this basic implementation - for (const auto& header : headers_) { - if (header.type == 1) { // LOAD - file.seekg(header.offset); - // Read `fileSize` bytes from `file` into the appropriate place in process + for (const auto& header : pheaders_) { + if (header.p_type == 1) { // LOAD + file.seekg(header.p_offset); + // Read `p_filesz` bytes from `file` into the appropriate place in process // memory - file.read(*imagePointer + header.virtualAddress, header.fileSize); + file.read(*imagePointer + header.p_vaddr, header.p_filesz); } } @@ -183,4 +193,10 @@ uint64_t Elf::getEntryPoint() const { return entryPoint_; } bool Elf::isValid() const { return isValid_; } +uint64_t Elf::getPhdrTableAddress() const { return phdrTableAddress_; } + +uint64_t Elf::getPHENT() const { return e_phentsize; } + +uint64_t Elf::getPHNUM() const { return e_phnum; } + } // namespace simeng diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index 31e36d7f48..94c4e0e152 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -32,6 +32,10 @@ LinuxProcess::LinuxProcess(const std::vector& commandLine, entryPoint_ = elf.getEntryPoint(); + phdrTableAddress_ = elf.getPhdrTableAddress(); + phent_ = elf.getPHENT(); + phnum_ = elf.getPHNUM(); + // Align heap start to a 32-byte boundary heapStart_ = alignToBoundary(elf.getProcessImageSize(), 32); @@ -160,7 +164,16 @@ void LinuxProcess::createStack(char** processImage) { // ELF auxillary vector, keys defined in `uapi/linux/auxvec.h` // TODO: populate remaining auxillary vector entries - initialStackFrame.push_back(6); // AT_PAGESZ + initialStackFrame.push_back(auxVec::AT_PHDR); // AT_PHDR + initialStackFrame.push_back(phdrTableAddress_); + + initialStackFrame.push_back(auxVec::AT_PHENT); // AT_PHENT + initialStackFrame.push_back(phent_); + + initialStackFrame.push_back(auxVec::AT_PHNUM); // AT_PHNUM + initialStackFrame.push_back(phnum_); + + initialStackFrame.push_back(auxVec::AT_PAGESZ); // AT_PAGESZ initialStackFrame.push_back(pageSize_); initialStackFrame.push_back(0); // null terminator From 6f8a3b83a31e64bdfc7d513c337a7d95019b2f74 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Mar 2023 12:22:20 +0000 Subject: [PATCH 019/115] Add entry point to auxvec --- src/lib/kernel/LinuxProcess.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index 94c4e0e152..31d3201c41 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -175,7 +175,12 @@ void LinuxProcess::createStack(char** processImage) { initialStackFrame.push_back(auxVec::AT_PAGESZ); // AT_PAGESZ initialStackFrame.push_back(pageSize_); - initialStackFrame.push_back(0); // null terminator + + initialStackFrame.push_back(auxVec::AT_ENTRY); // AT_ENTRY + initialStackFrame.push_back(entryPoint_); + + initialStackFrame.push_back(auxVec::AT_NULL); // null terminator + initialStackFrame.push_back(0); size_t stackFrameSize = initialStackFrame.size() * 8; From 3a4e38af7f824347b8319356cf5f03ac33d5b412 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Mar 2023 16:46:13 +0000 Subject: [PATCH 020/115] Add comments --- src/include/simeng/Elf.hh | 53 ++++++++++++++++++++++++++++++++-- src/lib/Elf.cc | 12 ++++---- src/lib/kernel/LinuxProcess.cc | 4 +-- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/include/simeng/Elf.hh b/src/include/simeng/Elf.hh index 0d41ba7aac..70ef7e4665 100644 --- a/src/include/simeng/Elf.hh +++ b/src/include/simeng/Elf.hh @@ -12,12 +12,35 @@ const char Format32 = 1; const char Format64 = 2; } // namespace ElfBitFormat +// Elf64_Phdr as described in the elf man page. Only contains SimEng relevant +// information + +// An executable or shared object file's program header table is an array of +// structures, each describing a segment or other information the system needs +// to prepare the program for execution. An object file segment contains one or +// more sections. Program headers are meaningful only for executable and shared +// object files. A file specifies its own program header size with the ELF +// header's e_phentsize and e_phnum members. The ELF program header is +// described by the type Elf32_Phdr or Elf64_Phdr depending on the architecture + struct Elf64_Phdr { + // Indicates what kind of segment this array element describes or + // how to interpret the array element's information uint32_t p_type; + // Holds the offset from the beginning of the file at + // which the first byte of the segment resides uint64_t p_offset; + // Holds the virtual address at which the first byte of the + // segment resides in memory uint64_t p_vaddr; + // On systems for which physical addressing is relevant, this + // member is reserved for the segment's physical address uint64_t p_paddr; + // Holds the number of bytes in the file image of + // the segment. It may be zero uint64_t p_filesz; + // Holds the number of bytes in the memory image + // of the segment. It may be zero uint64_t p_memsz; }; @@ -26,20 +49,46 @@ class Elf { public: Elf(std::string path, char** imagePointer); ~Elf(); + + /** Returns the process image size */ uint64_t getProcessImageSize() const; + + /** Returns if this ELF is valid */ bool isValid() const; + + /** Returns the entry point of the program */ uint64_t getEntryPoint() const; + + /** Returns the address of the program header table */ uint64_t getPhdrTableAddress() const; - uint64_t getPHENT() const; - uint64_t getPHNUM() const; + + /** Returns the size of a program header entry */ + uint64_t getPhdrEntrySize() const; + + /** Returns the number of program headers */ + uint64_t getNumPhdr() const; private: + /** The entry point of the program */ uint64_t entryPoint_; + + /** A vector holding each of the program headers extracted from the ELF */ std::vector pheaders_; + + /** The program header entry size stored in the ELF header */ uint16_t e_phentsize; + + /** The number of entries in the program header table stored in the ELF header + */ uint16_t e_phnum; + + /** Address of the program header table */ uint64_t phdrTableAddress_ = 0; + + /** Holds whether this ELF is valid for SimEng */ bool isValid_ = false; + + /** The size of the process image */ uint64_t processImageSize_; }; diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 027e0503e0..03e25d51b1 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -37,7 +37,7 @@ Elf::Elf(std::string path, char** imagePointer) { char fileMagic[4]; file.read(fileMagic, 4); if (std::memcmp(elfMagic, fileMagic, sizeof(elfMagic))) { - std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; + std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; return; } @@ -50,7 +50,7 @@ Elf::Elf(std::string path, char** imagePointer) { char bitFormat; file.read(&bitFormat, sizeof(bitFormat)); if (bitFormat != ElfBitFormat::Format64) { - std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" + std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" << std::endl; return; } @@ -87,8 +87,8 @@ Elf::Elf(std::string path, char** imagePointer) { * size. In the `elf64_hdr` * struct this value maps to the member `Elf64_Half e_phentsize`. * Starting from the 56th byte a 16-bit value represents the number - * of program header entries in the ELF Program header. In the `elf64_hdr` - * struct this value maps to `Elf64_Half e_phnum`. + * of program header entries in the ELF Program header table. In the + * `elf64_hdr` struct this value maps to `Elf64_Half e_phnum`. */ // Seek to the byte representing header entry size. @@ -195,8 +195,8 @@ bool Elf::isValid() const { return isValid_; } uint64_t Elf::getPhdrTableAddress() const { return phdrTableAddress_; } -uint64_t Elf::getPHENT() const { return e_phentsize; } +uint64_t Elf::getPhdrEntrySize() const { return e_phentsize; } -uint64_t Elf::getPHNUM() const { return e_phnum; } +uint64_t Elf::getNumPhdr() const { return e_phnum; } } // namespace simeng diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index 31d3201c41..56a02c4980 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -33,8 +33,8 @@ LinuxProcess::LinuxProcess(const std::vector& commandLine, entryPoint_ = elf.getEntryPoint(); phdrTableAddress_ = elf.getPhdrTableAddress(); - phent_ = elf.getPHENT(); - phnum_ = elf.getPHNUM(); + phent_ = elf.getPhdrEntrySize(); + phnum_ = elf.getNumPhdr(); // Align heap start to a 32-byte boundary heapStart_ = alignToBoundary(elf.getProcessImageSize(), 32); From fa60f72c718cb1d81287c793589fe6cf327a4850 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 22 Mar 2023 16:54:11 +0000 Subject: [PATCH 021/115] Refactor Linux Process variable names --- src/include/simeng/kernel/LinuxProcess.hh | 6 +++--- src/lib/Elf.cc | 2 ++ src/lib/kernel/LinuxProcess.cc | 12 ++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index 6dffbf0392..bfb89b36ce 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -115,13 +115,13 @@ class LinuxProcess { uint64_t entryPoint_ = 0; /** Program header table address */ - uint64_t phdrTableAddress_; + uint64_t progHeaderTableAddress_ = 0; /** Number of program headers */ - uint64_t phnum_; + uint64_t numProgHeaders_ = 0; /** Size of program header entry */ - uint64_t phent_; + uint64_t progHeaderEntSize_ = 0; /** The address of the start of the heap region. */ uint64_t heapStart_; diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 03e25d51b1..02ac8a0f8c 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -77,6 +77,8 @@ Elf::Elf(std::string path, char** imagePointer) { */ // Seek to the byte representing the start of the header offset table. + // Holds the program header table's file offset in bytes. If the file has no + // program header table, this member holds zero uint64_t e_phoff; file.read(reinterpret_cast(&e_phoff), sizeof(e_phoff)); diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index 56a02c4980..e3bc57df6f 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -32,9 +32,9 @@ LinuxProcess::LinuxProcess(const std::vector& commandLine, entryPoint_ = elf.getEntryPoint(); - phdrTableAddress_ = elf.getPhdrTableAddress(); - phent_ = elf.getPhdrEntrySize(); - phnum_ = elf.getNumPhdr(); + progHeaderTableAddress_ = elf.getPhdrTableAddress(); + progHeaderEntSize_ = elf.getPhdrEntrySize(); + numProgHeaders_ = elf.getNumPhdr(); // Align heap start to a 32-byte boundary heapStart_ = alignToBoundary(elf.getProcessImageSize(), 32); @@ -165,13 +165,13 @@ void LinuxProcess::createStack(char** processImage) { // ELF auxillary vector, keys defined in `uapi/linux/auxvec.h` // TODO: populate remaining auxillary vector entries initialStackFrame.push_back(auxVec::AT_PHDR); // AT_PHDR - initialStackFrame.push_back(phdrTableAddress_); + initialStackFrame.push_back(progHeaderTableAddress_); initialStackFrame.push_back(auxVec::AT_PHENT); // AT_PHENT - initialStackFrame.push_back(phent_); + initialStackFrame.push_back(progHeaderEntSize_); initialStackFrame.push_back(auxVec::AT_PHNUM); // AT_PHNUM - initialStackFrame.push_back(phnum_); + initialStackFrame.push_back(numProgHeaders_); initialStackFrame.push_back(auxVec::AT_PAGESZ); // AT_PAGESZ initialStackFrame.push_back(pageSize_); From 8fc367529bb0f6dbf16f5283c94fbdaf0dc459f1 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 24 Mar 2023 13:20:02 +0000 Subject: [PATCH 022/115] Comment and variable name updates --- src/include/simeng/Elf.hh | 16 +++++---- src/include/simeng/kernel/LinuxProcess.hh | 40 +++++++++++------------ src/lib/Elf.cc | 37 +++++++++++---------- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/include/simeng/Elf.hh b/src/include/simeng/Elf.hh index 70ef7e4665..96e9b0f06e 100644 --- a/src/include/simeng/Elf.hh +++ b/src/include/simeng/Elf.hh @@ -20,8 +20,9 @@ const char Format64 = 2; // to prepare the program for execution. An object file segment contains one or // more sections. Program headers are meaningful only for executable and shared // object files. A file specifies its own program header size with the ELF -// header's e_phentsize and e_phnum members. The ELF program header is -// described by the type Elf32_Phdr or Elf64_Phdr depending on the architecture +// header's e_phentsize and the number of headers with e_phnum members. The ELF +// program header is described by the type Elf32_Phdr or Elf64_Phdr depending on +// the architecture struct Elf64_Phdr { // Indicates what kind of segment this array element describes or @@ -56,10 +57,11 @@ class Elf { /** Returns if this ELF is valid */ bool isValid() const; - /** Returns the entry point of the program */ + /** Returns the virtual address to which the system first transfers + * control */ uint64_t getEntryPoint() const; - /** Returns the address of the program header table */ + /** Returns the virtual address of the program header table */ uint64_t getPhdrTableAddress() const; /** Returns the size of a program header entry */ @@ -76,13 +78,13 @@ class Elf { std::vector pheaders_; /** The program header entry size stored in the ELF header */ - uint16_t e_phentsize; + uint16_t e_phentsize_; /** The number of entries in the program header table stored in the ELF header */ - uint16_t e_phnum; + uint16_t e_phnum_; - /** Address of the program header table */ + /** Virtual address of the program header table */ uint64_t phdrTableAddress_ = 0; /** Holds whether this ELF is valid for SimEng */ diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index bfb89b36ce..2f13a7727d 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -9,26 +9,26 @@ namespace simeng { namespace kernel { namespace auxVec { -/** Labels for the entries in the auxiliary vector. */ +// Labels for the entries in the auxiliary vector enum labels { - AT_NULL = 0, /* end of vector */ - AT_IGNORE = 1, /* entry should be ignored */ - AT_EXECFD = 2, /* file descriptor of program */ - AT_PHDR = 3, /* program headers for program */ - AT_PHENT = 4, /* size of program header entry */ - AT_PHNUM = 5, /* number of program headers */ - AT_PAGESZ = 6, /* system page size */ - AT_BASE = 7, /* base address of interpreter */ - AT_FLAGS = 8, /* flags */ - AT_ENTRY = 9, /* entry point of program */ - AT_NOTELF = 10, /* program is not ELF */ - AT_UID = 11, /* real uid */ - AT_EUID = 12, /* effective uid */ - AT_GID = 13, /* real gid */ - AT_EGID = 14, /* effective gid */ - AT_PLATFORM = 15, /* string identifying CPU for optimizations */ - AT_HWCAP = 16, /* arch dependent hints at CPU capabilities */ - AT_CLKTCK = 17 /* frequency at which times() increments */ + AT_NULL = 0, // End of vector + AT_IGNORE = 1, // Entry should be ignored + AT_EXECFD = 2, // File descriptor of program + AT_PHDR = 3, // Program headers for program + AT_PHENT = 4, // Size of program header entry + AT_PHNUM = 5, // Number of program headers + AT_PAGESZ = 6, // System page size + AT_BASE = 7, // Base address of interpreter + AT_FLAGS = 8, // Flags + AT_ENTRY = 9, // Entry point of program + AT_NOTELF = 10, // Program is not ELF + AT_UID = 11, // Real uid + AT_EUID = 12, // Effective uid + AT_GID = 13, // Real gid + AT_EGID = 14, // Effective gid + AT_PLATFORM = 15, // String identifying CPU for optimizations + AT_HWCAP = 16, // Arch dependent hints at CPU capabilities + AT_CLKTCK = 17 // Frequency at which times() increments }; } // namespace auxVec @@ -114,7 +114,7 @@ class LinuxProcess { /** The entry point of the process. */ uint64_t entryPoint_ = 0; - /** Program header table address */ + /** Program header table virtual address */ uint64_t progHeaderTableAddress_ = 0; /** Number of program headers */ diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 02ac8a0f8c..88f36f0602 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -79,35 +79,35 @@ Elf::Elf(std::string path, char** imagePointer) { // Seek to the byte representing the start of the header offset table. // Holds the program header table's file offset in bytes. If the file has no // program header table, this member holds zero - uint64_t e_phoff; + uint64_t e_phoff = 0; file.read(reinterpret_cast(&e_phoff), sizeof(e_phoff)); /** - * Starting from the 54th byte of the ELF Header a 16-bit value indicates - * the the size in bytes of one entry in the - * file's program header table; all entries are the same - * size. In the `elf64_hdr` - * struct this value maps to the member `Elf64_Half e_phentsize`. - * Starting from the 56th byte a 16-bit value represents the number - * of program header entries in the ELF Program header table. In the - * `elf64_hdr` struct this value maps to `Elf64_Half e_phnum`. + * Starting from the 54th byte of the ELF Header a 16-bit value indicates the + * size in bytes of one entry in the file's program header table; all entries + * are the same size. In the `elf64_hdr` struct this value maps to the member + * `Elf64_Half e_phentsize`. */ - // Seek to the byte representing header entry size. file.seekg(0x36); - file.read(reinterpret_cast(&e_phentsize), sizeof(e_phentsize)); - file.read(reinterpret_cast(&e_phnum), sizeof(e_phnum)); + file.read(reinterpret_cast(&e_phentsize_), sizeof(e_phentsize_)); + + /** Starting from the 56th byte a 16-bit value represents the number + * of program header entries in the ELF Program header table. In the + * `elf64_hdr` struct this value maps to `Elf64_Half e_phnum`. + */ + file.read(reinterpret_cast(&e_phnum_), sizeof(e_phnum_)); // Resize the header to equal the number of header entries. - pheaders_.resize(e_phnum); + pheaders_.resize(e_phnum_); processImageSize_ = 0; // Loop over all headers and extract them. - for (size_t i = 0; i < e_phnum; i++) { + for (size_t i = 0; i < e_phnum_; i++) { // Since all headers entries have the same size. // We can extract the nth header using the header offset // and header entry size. - file.seekg(e_phoff + (i * e_phentsize)); + file.seekg(e_phoff + (i * e_phentsize_)); auto& header = pheaders_[i]; /** @@ -157,7 +157,8 @@ Elf::Elf(std::string path, char** imagePointer) { processImageSize_ = header.p_vaddr + header.p_memsz; } - // Find the table address used to populate the auxvec + // Determine the virtual address of the header table in memory from + // individual program headers. Used to populate the auxvec if (header.p_offset <= e_phoff && e_phoff < header.p_offset + header.p_filesz) { phdrTableAddress_ = header.p_vaddr + (e_phoff - header.p_offset); @@ -197,8 +198,8 @@ bool Elf::isValid() const { return isValid_; } uint64_t Elf::getPhdrTableAddress() const { return phdrTableAddress_; } -uint64_t Elf::getPhdrEntrySize() const { return e_phentsize; } +uint64_t Elf::getPhdrEntrySize() const { return e_phentsize_; } -uint64_t Elf::getNumPhdr() const { return e_phnum; } +uint64_t Elf::getNumPhdr() const { return e_phnum_; } } // namespace simeng From 4b9aa60a67efeafc06130a5755e528455362418a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 24 Mar 2023 13:23:51 +0000 Subject: [PATCH 023/115] Update spacing --- src/lib/Elf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 88f36f0602..6a2e71aba3 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -37,7 +37,7 @@ Elf::Elf(std::string path, char** imagePointer) { char fileMagic[4]; file.read(fileMagic, 4); if (std::memcmp(elfMagic, fileMagic, sizeof(elfMagic))) { - std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; + std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; return; } @@ -50,7 +50,7 @@ Elf::Elf(std::string path, char** imagePointer) { char bitFormat; file.read(&bitFormat, sizeof(bitFormat)); if (bitFormat != ElfBitFormat::Format64) { - std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" + std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" << std::endl; return; } From 0ce163961bbdfea77f23f8b0700c323157026af8 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 24 Mar 2023 14:54:47 +0000 Subject: [PATCH 024/115] Create function to return pending slots in pipeline buffer --- src/include/simeng/pipeline/PipelineBuffer.hh | 8 ++++++++ src/lib/models/inorder/Core.cc | 13 +++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/include/simeng/pipeline/PipelineBuffer.hh b/src/include/simeng/pipeline/PipelineBuffer.hh index b827d6f037..85d5d79ff6 100644 --- a/src/include/simeng/pipeline/PipelineBuffer.hh +++ b/src/include/simeng/pipeline/PipelineBuffer.hh @@ -29,6 +29,14 @@ class PipelineBuffer { headIsStart = !headIsStart; } + const T* getPendingSlots() const { + if (isStalled_) { + return getTailSlots(); + } else { + return getHeadSlots(); + } + } + /** Get a tail slots pointer. */ T* getTailSlots() { T* ptr = buffer.data(); diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index 9c7c388e9d..e57fda264f 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -121,20 +121,13 @@ bool Core::hasHalted() const { // Units place uops in buffer tail, but if buffer is stalled, uops do not // move to head slots and so remain in tail slots. Buffer head appears // empty. Check emptiness accordingly - auto decSlots = fetchToDecodeBuffer_.isStalled() - ? fetchToDecodeBuffer_.getTailSlots()[0] - : fetchToDecodeBuffer_.getHeadSlots()[0]; + auto decSlots = fetchToDecodeBuffer_.getPendingSlots()[0]; bool decodePending = decSlots.size() > 0; - auto exeSlots = decodeToExecuteBuffer_.isStalled() - ? decodeToExecuteBuffer_.getTailSlots()[0] - : decodeToExecuteBuffer_.getHeadSlots()[0]; + auto exeSlots = decodeToExecuteBuffer_.getPendingSlots()[0]; bool executePending = exeSlots != nullptr; - auto writeSlots = completionSlots_[0].isStalled() - ? completionSlots_[0].getTailSlots()[0] - : completionSlots_[0].getHeadSlots()[0]; - + auto writeSlots = completionSlots_[0].getPendingSlots()[0]; bool writebackPending = writeSlots != nullptr; return (fetchUnit_.hasHalted() && !decodePending && !writebackPending && From 785ec468984acce72192437142fa75e6058938dd Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 24 Mar 2023 18:04:57 +0000 Subject: [PATCH 025/115] Fix typos --- CMakeLists.txt | 2 +- configs/DEMO_RISCV.yaml | 6 +++--- configs/sst-cores/a64fx-sst.yaml | 2 +- .../developer/arch/supported/aarch64.rst | 2 +- .../simeng/FixedLatencyMemoryInterface.hh | 2 +- src/include/simeng/FlatMemoryInterface.hh | 2 +- src/include/simeng/MemoryInterface.hh | 2 +- .../simeng/arch/aarch64/MicroDecoder.hh | 4 ++-- .../simeng/arch/aarch64/helpers/float.hh | 2 +- src/include/simeng/pipeline/ReorderBuffer.hh | 2 +- src/lib/CoreInstance.cc | 2 +- src/lib/GenericPredictor.cc | 2 +- src/lib/arch/aarch64/Architecture.cc | 2 +- src/lib/arch/aarch64/ExceptionHandler.cc | 4 ++-- src/lib/arch/aarch64/InstructionMetadata.cc | 18 +++++++++--------- src/lib/arch/aarch64/Instruction_address.cc | 2 +- src/lib/arch/aarch64/Instruction_decode.cc | 8 ++++---- src/lib/arch/aarch64/Instruction_execute.cc | 4 ++-- src/lib/arch/riscv/ExceptionHandler.cc | 4 ++-- src/lib/kernel/LinuxProcess.cc | 8 ++++---- src/lib/models/inorder/Core.cc | 2 +- src/lib/models/outoforder/Core.cc | 2 +- src/lib/pipeline/A64FXPortAllocator.cc | 2 +- src/lib/pipeline/FetchUnit.cc | 2 +- src/lib/pipeline/LoadStoreQueue.cc | 8 ++++---- sst/config/a64fx-config.py | 2 +- test/regression/aarch64/LoadStoreQueue.cc | 2 +- test/regression/aarch64/Syscall.cc | 8 ++++---- .../aarch64/instructions/bitmanip.cc | 12 ++++++------ test/regression/riscv/LoadStoreQueue.cc | 2 +- test/regression/riscv/Syscall.cc | 4 ++-- test/unit/pipeline/A64FXPortAllocatorTest.cc | 4 ++-- 32 files changed, 65 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f08650c10a..e2685dd2f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,7 +196,7 @@ if(SIMENG_ENABLE_TESTS) PATHS "${llvm_BINARY_DIR}/lib/cmake/llvm") # NOTE: we don't do the usual version checks here because it needs vars exported in find_LLVM - # we just assume it's good beacuse it must be whitelisted in FetchContent_Declare + # we just assume it's good because it must be whitelisted in FetchContent_Declare endif() set(SIMENG_LLVM_VERSION ${LLVM_VERSION_MAJOR} CACHE INTERNAL "LLVM major version number used.") diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 87a2059ccb..515e39e7f6 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -5,7 +5,7 @@ Core: ISA: rv64 - Simulation-Mode: inorderpipelined + Simulation-Mode: outoforder Clock-Frequency: 2.5 # Timer-Frequency is in MHz. Timer-Frequency: 200 @@ -34,7 +34,7 @@ Branch-Predictor: RAS-entries: 5 Fallback-Static-Predictor: "Always-Taken" L1-Data-Memory: - Interface-Type: Flat + Interface-Type: Fixed L1-Instruction-Memory: Interface-Type: Flat LSQ-L1-Interface: @@ -146,7 +146,7 @@ CPU-Info: Core-Count: 1 # Socket-Count MUST be 1 as multi-socket simulations are not supported at this time. (TX2 true value is 2) Socket-Count: 1 - # SMT MUST be 1 as Simultanious-Multi-Threading is not supported at this time. (TX2 true value is 4) + # SMT MUST be 1 as Simultaneous-Multi-Threading is not supported at this time. (TX2 true value is 4) SMT: 1 # Below are the values needed to generate /proc/cpuinfo BogoMIPS: 400.00 diff --git a/configs/sst-cores/a64fx-sst.yaml b/configs/sst-cores/a64fx-sst.yaml index 643398b6ed..8b466d56c6 100644 --- a/configs/sst-cores/a64fx-sst.yaml +++ b/configs/sst-cores/a64fx-sst.yaml @@ -255,7 +255,7 @@ CPU-Info: Core-Count: 1 # Socket-Count MUST be 1 as multi-socket simulations are not supported at this time. (A64FX true value is 1) Socket-Count: 1 - # SMT MUST be 1 as Simultanious-Multi-Threading is not supported at this time. (A64FX true value is 1) + # SMT MUST be 1 as Simultaneous-Multi-Threading is not supported at this time. (A64FX true value is 1) SMT: 1 # Below are the values needed to generate /proc/cpuinfo BogoMIPS: 200.00 diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 2704445e23..fbe39b75cf 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -160,7 +160,7 @@ Also supported is the Arm SME extension and thus the use of ``ZA`` sub-tile regi SME instructions can also operate on sub-tile slices; individual rows or columns within a sub-tile. Regardless of whether a whole sub-tile or a slice is used as a source operand, all rows associated with said tile will be added to the ``operands`` vector. There are two reasons for this. First, the index value pointing to the relevant slice cannot be evaluated before instruction execution, thus, all sub-tile rows need to be provided. Second, if the source slice is a vertical slice (or a column of the sub-tile) then an element from each row is needed to construct the correct output. -Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targetted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``operands`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. +Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``operands`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. Before implementing any SME functionality we highly recommend familiarising yourself with the specification; found `here `_. diff --git a/src/include/simeng/FixedLatencyMemoryInterface.hh b/src/include/simeng/FixedLatencyMemoryInterface.hh index dddbf9eca5..11ec5e8a5e 100644 --- a/src/include/simeng/FixedLatencyMemoryInterface.hh +++ b/src/include/simeng/FixedLatencyMemoryInterface.hh @@ -57,7 +57,7 @@ class FixedLatencyMemoryInterface : public MemoryInterface { /** Clear the completed reads. */ void clearCompletedReads() override; - /** Returns true if there are any oustanding memory requests in-flight. */ + /** Returns true if there are any outstanding memory requests in-flight. */ bool hasPendingRequests() const override; /** Tick the memory model to process the request queue. */ diff --git a/src/include/simeng/FlatMemoryInterface.hh b/src/include/simeng/FlatMemoryInterface.hh index f85e2f8491..c1ee653e20 100644 --- a/src/include/simeng/FlatMemoryInterface.hh +++ b/src/include/simeng/FlatMemoryInterface.hh @@ -27,7 +27,7 @@ class FlatMemoryInterface : public MemoryInterface { /** Clear the completed reads. */ void clearCompletedReads() override; - /** Returns true if there are any oustanding memory requests in-flight. */ + /** Returns true if there are any outstanding memory requests in-flight. */ bool hasPendingRequests() const override; /** Tick: do nothing */ diff --git a/src/include/simeng/MemoryInterface.hh b/src/include/simeng/MemoryInterface.hh index aeddc57d0c..4c6da56980 100644 --- a/src/include/simeng/MemoryInterface.hh +++ b/src/include/simeng/MemoryInterface.hh @@ -63,7 +63,7 @@ class MemoryInterface { /** Clear the completed reads. */ virtual void clearCompletedReads() = 0; - /** Returns true if there are any oustanding memory requests in-flight. */ + /** Returns true if there are any outstanding memory requests in-flight. */ virtual bool hasPendingRequests() const = 0; /** Tick the memory interface to allow it to process internal tasks. diff --git a/src/include/simeng/arch/aarch64/MicroDecoder.hh b/src/include/simeng/arch/aarch64/MicroDecoder.hh index 22f0cb89b4..54a3440b2e 100644 --- a/src/include/simeng/arch/aarch64/MicroDecoder.hh +++ b/src/include/simeng/arch/aarch64/MicroDecoder.hh @@ -20,7 +20,7 @@ struct OpType { */ class MicroDecoder { public: - /** Construct a micro decoder for splitting relevant instructons. */ + /** Construct a micro decoder for splitting relevant instructions. */ MicroDecoder(YAML::Node config); ~MicroDecoder(); @@ -67,7 +67,7 @@ class MicroDecoder { /** A micro-decoding cache, mapping an instruction word to a previously split * instruction. Instructions are added to the cache as they're split into - * their repsective micro-operations, to reduce the overhead of future + * their respective micro-operations, to reduce the overhead of future * splitting. */ static std::unordered_map> microDecodeCache; diff --git a/src/include/simeng/arch/aarch64/helpers/float.hh b/src/include/simeng/arch/aarch64/helpers/float.hh index 05261173de..169f4d56a7 100644 --- a/src/include/simeng/arch/aarch64/helpers/float.hh +++ b/src/include/simeng/arch/aarch64/helpers/float.hh @@ -138,7 +138,7 @@ class floatHelp { * D represents the destination vector register type (e.g. for dd, D = * double). * N represents the source vector register type (e.g. for wn, N = int32_t). - * Returns correctly formated RegisterValue. */ + * Returns correctly formatted RegisterValue. */ template static RegisterValue scvtf_FixedPoint( std::vector& operands, diff --git a/src/include/simeng/pipeline/ReorderBuffer.hh b/src/include/simeng/pipeline/ReorderBuffer.hh index 22278350d5..179d9bb689 100644 --- a/src/include/simeng/pipeline/ReorderBuffer.hh +++ b/src/include/simeng/pipeline/ReorderBuffer.hh @@ -142,7 +142,7 @@ class ReorderBuffer { /** The number of instructions committed. */ uint64_t instructionsCommitted_ = 0; - /** The number of speculatived loads which violated load-store ordering. */ + /** The number of speculative loads which violated load-store ordering. */ uint64_t loadViolations_ = 0; }; diff --git a/src/lib/CoreInstance.cc b/src/lib/CoreInstance.cc index ddf53b20bf..c3a1017480 100644 --- a/src/lib/CoreInstance.cc +++ b/src/lib/CoreInstance.cc @@ -80,7 +80,7 @@ void CoreInstance::generateCoreModel(std::string executablePath, } void CoreInstance::setSimulationMode() { - // Get the simualtion mode as defined by the set configuration, defaulting to + // Get the simulation mode as defined by the set configuration, defaulting to // emulation if (config_["Core"]["Simulation-Mode"].as() == "inorderpipelined") { diff --git a/src/lib/GenericPredictor.cc b/src/lib/GenericPredictor.cc index 2539d7ae59..17886f0e0c 100644 --- a/src/lib/GenericPredictor.cc +++ b/src/lib/GenericPredictor.cc @@ -39,7 +39,7 @@ BranchPrediction GenericPredictor::predict(uint64_t address, BranchType type, (knownTarget != 0) ? address + knownTarget : btb_[hashedIndex].second; BranchPrediction prediction = {direction, target}; - // Ammend prediction based on branch type + // Amend prediction based on branch type if (type == BranchType::Unconditional) { prediction.taken = true; } else if (type == BranchType::Return) { diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 57d1a1c2ff..62e41adf6f 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -211,7 +211,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, } ExecutionInfo Architecture::getExecutionInfo(Instruction& insn) const { - // Asusme no opcode-based override + // Assume no opcode-based override ExecutionInfo exeInfo = groupExecutionInfo_.at(insn.getGroup()); if (opcodeExecutionInfo_.find(insn.getMetadata().opcode) != opcodeExecutionInfo_.end()) { diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 88f796f495..1308267948 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -453,14 +453,14 @@ bool ExceptionHandler::init() { } case 134: { // rt_sigaction // TODO: Implement syscall logic. Ignored for now as it's assumed the - // current use of this syscall is to setup error handlers. Simualted + // current use of this syscall is to setup error handlers. Simulated // code is expected to work so no need for these handlers. stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; } case 135: { // rt_sigprocmask // TODO: Implement syscall logic. Ignored for now as it's assumed the - // current use of this syscall is to setup error handlers. Simualted + // current use of this syscall is to setup error handlers. Simulated // code is expected to work so no need for these handlers. stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index c2ef75b6b8..1c31b0cdf4 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -758,7 +758,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].mem.disp = std::stoi(operandStr.substr(startPos, immSize)); } else { - // double or tripple digit immediates are converted to hex, and so + // double or triple digit immediates are converted to hex, and so // require a different conversion to uint operands[2].mem.disp = std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); @@ -824,7 +824,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount = 3; operands[2].type = ARM64_OP_IMM; operands[2].access = CS_AC_READ; - // For vector arrangment of 16-bit, post_index immediate is 2 + // For vector arrangement of 16-bit, post_index immediate is 2 operands[2].imm = 2; break; case Opcode::AArch64_LD1Rv1d_POST: @@ -836,7 +836,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount = 3; operands[2].type = ARM64_OP_IMM; operands[2].access = CS_AC_READ; - // For vector arrangment of 64-bit, post_index immediate is 8 + // For vector arrangement of 64-bit, post_index immediate is 8 operands[2].imm = 8; break; case Opcode::AArch64_LD1Rv16b_POST: @@ -849,7 +849,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount = 3; operands[2].type = ARM64_OP_IMM; operands[2].access = CS_AC_READ; - // For vector arrangment of 8-bit, post_index immediate is 1 + // For vector arrangement of 8-bit, post_index immediate is 1 operands[2].imm = 1; break; case Opcode::AArch64_LD1Rv2s_POST: @@ -862,7 +862,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount = 3; operands[2].type = ARM64_OP_IMM; operands[2].access = CS_AC_READ; - // For vector arrangment of 32-bit, post_index immediate is 4 + // For vector arrangement of 32-bit, post_index immediate is 4 operands[2].imm = 4; break; case Opcode::AArch64_LD1Onev16b: @@ -1265,7 +1265,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].mem.disp = std::stoi(operandStr.substr(startPos, immSize)); } else { - // double or tripple digit immediates are converted to hex, and so + // double or triple digit immediates are converted to hex, and so // require a different conversion to uint operands[2].mem.disp = std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); @@ -1307,7 +1307,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // ST2 post incorrectly flags read and write operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ | CS_AC_WRITE; - // Another incorrect acess flag for register offset operand + // Another incorrect access flag for register offset operand if (operandCount == 4) { operands[3].access = CS_AC_READ; } @@ -1539,7 +1539,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Need to add access specifiers // although operands[0] should be READ | WRITE, due to the implemented // decode logic for SME tile destinations, the register will be added as - // both source and distination with just WRITE access. + // both source and destination with just WRITE access. operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; @@ -2064,7 +2064,7 @@ void InstructionMetadata::revertAliasing() { // mov Zd.T, Pg/M, Zn.T; alias for: sel Zd.T, Pg, Zn.T, Zd.T if (mnemonic[0] == 'm') { // SEL instructions id sometimes set as ARM64_INS_MOV even if - // aliasing hasn't occured so double check mnemoic is MOV alias + // aliasing hasn't occurred so double check mnemonic is MOV alias operandCount = 4; operands[3] = operands[0]; operands[3].access = CS_AC_READ; diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index d1068fde2c..5512da5647 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -44,7 +44,7 @@ span Instruction::generateAddresses() { break; } } else { - // 0th bit of SVCR register determins if streaming-mode is enabled. + // 0th bit of SVCR register determines if streaming-mode is enabled. const bool SMenabled = architecture_.getSVCRval() & 1; // When streaming mode is enabled, the architectural vector length goes from // SVE's VL to SME's SVL. diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 3c0a4dfee3..4e60ae1b62 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -136,7 +136,7 @@ Register csRegToRegister(arm64_reg reg) { std::numeric_limits::max()}; } -/** Resturns a full set of rows from the ZA matrix register that make up the +/** Returns a full set of rows from the ZA matrix register that make up the * supplied SME tile register. */ std::vector getZARowVectors(arm64_reg reg, const uint64_t SVL_bits) { std::vector outRegs; @@ -211,7 +211,7 @@ void Instruction::decode() { op.reg != ARM64_REG_XZR) { // Determine the data type the instruction operates on based on the // register operand used - // Belongs to the predicate group if the detsination register is a + // Belongs to the predicate group if the destination register is a // predicate if (op.reg >= ARM64_REG_V0) { isVectorData_ = true; @@ -293,7 +293,7 @@ void Instruction::decode() { isSMEData_ = true; regs = getZARowVectors(op.sme_index.reg, architecture_.getStreamingVectorLength()); - // If WRITE, then also need to add to souce registers to maintain + // If WRITE, then also need to add to source registers to maintain // un-updated rows for (int i = 0; i < regs.size(); i++) { sourceRegisters.push_back(regs[i]); @@ -616,7 +616,7 @@ void Instruction::decode() { } // Catch exceptions to the above identifier assignments - // Uncaught preciate assignment due to lacking destination register + // Uncaught predicate assignment due to lacking destination register if (metadata.opcode == Opcode::AArch64_PTEST_PP) { isPredicate_ = true; } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 6e4752adae..b8964c2224 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -68,9 +68,9 @@ void Instruction::execute() { assert( canExecute() && "Attempted to execute an instruction before all operands were provided"); - // 0th bit of SVCR register determins if streaming-mode is enabled. + // 0th bit of SVCR register determines if streaming-mode is enabled. const bool SMenabled = architecture_.getSVCRval() & 1; - // 1st bit of SVCR register determins if ZA register is enabled. + // 1st bit of SVCR register determines if ZA register is enabled. const bool ZAenabled = architecture_.getSVCRval() & 2; // When streaming mode is enabled, the architectural vector length goes from // SVE's VL to SME's SVL. diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index ef8bd1bab7..5f063f07ea 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -454,14 +454,14 @@ bool ExceptionHandler::init() { } case 134: { // rt_sigaction // TODO: Implement syscall logic. Ignored for now as it's assumed the - // current use of this syscall is to setup error handlers. Simualted + // current use of this syscall is to setup error handlers. Simulated // code is expected to work so no need for these handlers. stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; } case 135: { // rt_sigprocmask // TODO: Implement syscall logic. Ignored for now as it's assumed the - // current use of this syscall is to setup error handlers. Simualted + // current use of this syscall is to setup error handlers. Simulated // code is expected to work so no need for these handlers. stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index e3bc57df6f..b61470919c 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -138,7 +138,7 @@ void LinuxProcess::createStack(char** processImage) { for (int i = 0; i < env.size(); i++) { stringBytes.push_back(env.c_str()[i]); } - // Null entry to seperate strings + // Null entry to separate strings stringBytes.push_back(0); } @@ -149,7 +149,7 @@ void LinuxProcess::createStack(char** processImage) { initialStackFrame.push_back(stackPointer_); // argv[0] ptr for (int i = 0; i < stringBytes.size(); i++) { if (ptrCount == commandLine_.size()) { - // null terminator to seperate argv and env strings + // null terminator to separate argv and env strings initialStackFrame.push_back(0); ptrCount++; } @@ -162,8 +162,8 @@ void LinuxProcess::createStack(char** processImage) { initialStackFrame.push_back(0); // null terminator - // ELF auxillary vector, keys defined in `uapi/linux/auxvec.h` - // TODO: populate remaining auxillary vector entries + // ELF auxiliary vector, keys defined in `uapi/linux/auxvec.h` + // TODO: populate remaining auxiliary vector entries initialStackFrame.push_back(auxVec::AT_PHDR); // AT_PHDR initialStackFrame.push_back(progHeaderTableAddress_); diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index fdfba8cc02..6d609d93d9 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -311,7 +311,7 @@ void Core::readRegisters() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - // Update registers in accoradance with the ProcessStateChange type + // Update registers in accordance with the ProcessStateChange type switch (change.type) { case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index 3dd86a7ad2..4df7732c20 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -324,7 +324,7 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - // Update registers in accoradance with the ProcessStateChange type + // Update registers in accordance with the ProcessStateChange type switch (change.type) { case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { diff --git a/src/lib/pipeline/A64FXPortAllocator.cc b/src/lib/pipeline/A64FXPortAllocator.cc index ba1db0471e..d7cb9626ee 100644 --- a/src/lib/pipeline/A64FXPortAllocator.cc +++ b/src/lib/pipeline/A64FXPortAllocator.cc @@ -9,7 +9,7 @@ namespace pipeline { A64FXPortAllocator::A64FXPortAllocator( const std::vector>& portArrangement) - : // Initiliase reservation station to port mapping + : // Initialise reservation station to port mapping rsToPort_({{0, 1, 2}, {3, 4}, {5}, {6}, {7}}) {} uint16_t A64FXPortAllocator::allocate(const std::vector& ports) { diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index ade3d307c0..b80c25b1b3 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -124,7 +124,7 @@ void FetchUnit::tick() { break; } - // Create branch prediction after identifing instruction type + // Create branch prediction after identifying instruction type // (e.g. RET, BL, etc). BranchPrediction prediction = {false, 0}; if (macroOp[0]->isBranch()) { diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index 2189e6feca..742e3bc791 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -110,7 +110,7 @@ void LoadStoreQueue::startLoad(const std::shared_ptr& insn) { .back() .reqAddresses; // Store load addresses temporarily so that conflictions are - // only regsitered once on most recent (program order) store + // only registered once on most recent (program order) store std::list temp_load_addr(ld_addresses.begin(), ld_addresses.end()); @@ -174,7 +174,7 @@ void LoadStoreQueue::supplyStoreData(const std::shared_ptr& insn) { while (itSt != storeQueue_.end()) { auto& entry = itSt->first; // Pair entry and incoming store data operation with macroOp identifier and - // microOp index value pre-detemined in microDecoder + // microOp index value pre-determined in microDecoder if (entry->getInstructionId() == macroOpNum && entry->getMicroOpIndex() == microOpNum) { // Supply data to be stored by operations @@ -435,7 +435,7 @@ void LoadStoreQueue::tick() { // No more requests of this type can be scheduled this cycle exceededLimits[isStore] = true; // Remove speculative increment to ensure it doesn't count for - // comparisons aginast the totalLimit_ + // comparisons against the totalLimit_ reqCounts[isStore]--; break; } else { @@ -445,7 +445,7 @@ void LoadStoreQueue::tick() { while (addressQueue.size()) { const simeng::MemoryAccessTarget req = addressQueue.front(); - // Ensure the limit on the data transfered per cycle is adhered to + // Ensure the limit on the data transferred per cycle is adhered to assert(req.size <= bandwidth && "Individual memory request from LoadStoreQueue exceeds L1 " "bandwidth set and thus will never be submitted"); diff --git a/sst/config/a64fx-config.py b/sst/config/a64fx-config.py index 13f9eb4942..703dd32995 100644 --- a/sst/config/a64fx-config.py +++ b/sst/config/a64fx-config.py @@ -52,7 +52,7 @@ def getMemoryProps(memory_size: int, si: str): A64FX_HL_L1 = 5 # Hit latency of A64FX L2 cache (cycles). A64FX_HL_L2 = 56 -# Cohenrence protocol of A64FX caches. +# Coherence protocol of A64FX caches. A64FX_COHP = "MESI" # L1 & L2 cache type of A64FX. A64FX_CACHE_TYPE = "inclusive" diff --git a/test/regression/aarch64/LoadStoreQueue.cc b/test/regression/aarch64/LoadStoreQueue.cc index 1d7e317dfc..2892e0f6fb 100644 --- a/test/regression/aarch64/LoadStoreQueue.cc +++ b/test/regression/aarch64/LoadStoreQueue.cc @@ -23,7 +23,7 @@ TEST_P(LoadStoreQueue, RAW) { EXPECT_EQ(getGeneralRegister(2), 42u); } -// Test multiple simulteneous RAW violations are flushed correctly. +// Test multiple simultaneous RAW violations are flushed correctly. TEST_P(LoadStoreQueue, RAWx2) { initialHeapData_.resize(8); reinterpret_cast(initialHeapData_.data())[0] = -1; diff --git a/test/regression/aarch64/Syscall.cc b/test/regression/aarch64/Syscall.cc index eed2208d9c..5d316197dc 100644 --- a/test/regression/aarch64/Syscall.cc +++ b/test/regression/aarch64/Syscall.cc @@ -24,7 +24,7 @@ TEST_P(Syscall, getrandom) { mov x8, 214 svc #0 - # store inital heap address + # store initial heap address mov x10, x0 # Save 8 random bytes to the heap @@ -51,7 +51,7 @@ TEST_P(Syscall, getrandom) { getMemoryValue(heapStart + 8 + i)); } - // check that the retuned bytes arent all equal to -1. + // check that the returned bytes aren't all equal to -1. // heap was initialised to -1 so check bytes have changed bool allUnchanged = true; for (size_t i = 0; i < 16; i++) { @@ -62,8 +62,8 @@ TEST_P(Syscall, getrandom) { } EXPECT_EQ(allUnchanged, false); - // Check that the returned bytes from the two syscalls dont all match. - // If they do then the returned bytes surely werent random + // Check that the returned bytes from the two syscalls don't all match. + // If they do then the returned bytes surely weren't random bool allMatch = true; for (char i = 0; i < 8; i++) { if (getMemoryValue(heapStart + i) != diff --git a/test/regression/aarch64/instructions/bitmanip.cc b/test/regression/aarch64/instructions/bitmanip.cc index f44f620a06..479222a3be 100644 --- a/test/regression/aarch64/instructions/bitmanip.cc +++ b/test/regression/aarch64/instructions/bitmanip.cc @@ -7,7 +7,7 @@ using InstBitmanip = AArch64RegressionTest; TEST_P(InstBitmanip, bfm) { // 32-bit RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov w0, wzr sub w1, w0, #1 sub w2, w0, #1 @@ -29,7 +29,7 @@ TEST_P(InstBitmanip, bfm) { // 64-bit RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov x0, xzr sub x1, x0, #1 sub x2, x0, #1 @@ -172,7 +172,7 @@ TEST_P(InstBitmanip, rev) { TEST_P(InstBitmanip, sbfm) { // 32-bit RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov w0, wzr sub w1, w0, #1 sub w2, w0, #1 @@ -207,7 +207,7 @@ TEST_P(InstBitmanip, sbfm) { // 64-bit RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov x0, xzr sub x1, x0, #1 sub x2, x0, #1 @@ -248,7 +248,7 @@ TEST_P(InstBitmanip, sbfm) { TEST_P(InstBitmanip, ubfm) { // 32-bit RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov w0, wzr sub w1, w0, #1 sub w2, w0, #1 @@ -269,7 +269,7 @@ TEST_P(InstBitmanip, ubfm) { EXPECT_EQ(getGeneralRegister(4), 0x01E80000ull); RUN_AARCH64(R"( - # Fill desintation registers with 1s + # Fill destination registers with 1s mov x0, xzr sub x1, x0, #1 sub x2, x0, #1 diff --git a/test/regression/riscv/LoadStoreQueue.cc b/test/regression/riscv/LoadStoreQueue.cc index 4f84f2c143..c5bd89096c 100644 --- a/test/regression/riscv/LoadStoreQueue.cc +++ b/test/regression/riscv/LoadStoreQueue.cc @@ -22,7 +22,7 @@ TEST_P(LoadStoreQueue, RAW) { EXPECT_EQ(getGeneralRegister(7), 42u); } -// Test multiple simulteneous RAW violations are flushed correctly. +// Test multiple simultaneous RAW violations are flushed correctly. TEST_P(LoadStoreQueue, RAWx2) { initialHeapData_.resize(8); reinterpret_cast(initialHeapData_.data())[0] = -1; diff --git a/test/regression/riscv/Syscall.cc b/test/regression/riscv/Syscall.cc index fc324cdddf..8a7c2b14ab 100644 --- a/test/regression/riscv/Syscall.cc +++ b/test/regression/riscv/Syscall.cc @@ -25,7 +25,7 @@ TEST_P(Syscall, getrandom) { li a7, 214 ecall - # store inital heap address + # store initial heap address mv t0, a0 # Save 8 random bytes to the heap @@ -63,7 +63,7 @@ TEST_P(Syscall, getrandom) { EXPECT_EQ(allUnchanged, false); // Check that the returned bytes from the two syscalls dont all match. - // If they do then the returned bytes surely werent random + // If they do then the returned bytes surely weren't random bool allMatch = true; for (char i = 0; i < 8; i++) { if (getMemoryValue(heapStart + i) != diff --git a/test/unit/pipeline/A64FXPortAllocatorTest.cc b/test/unit/pipeline/A64FXPortAllocatorTest.cc index e949f6156b..2e7b5df70b 100644 --- a/test/unit/pipeline/A64FXPortAllocatorTest.cc +++ b/test/unit/pipeline/A64FXPortAllocatorTest.cc @@ -257,7 +257,7 @@ TEST(A64FXPortAllocator, dispatchSlots) { rsFreeEntries = {10, 10, 10, 10, 19}; // With less than 4 instructions dispatched in a cycle, the next cycle should - // reset the displatchSlot to 0 and start the allocation logic at the + // reset the dispatchSlot to 0 and start the allocation logic at the // appropriate place in the mechanism portAllocator.tick(); EXPECT_EQ(portAllocator.allocate({2, 4, 5, 6}), 2); @@ -273,7 +273,7 @@ TEST(A64FXPortAllocator, dispatchSlots) { EXPECT_EQ(portAllocator.allocate({2, 4, 5, 6}), 2); rsFreeEntries[0]--; - // Dispatch slot values should be shared amoungst all instruction attribute + // Dispatch slot values should be shared amongst all instruction attribute // dispatch mechanisms rsFreeEntries = {10, 10, 10, 10, 19}; portAllocator.tick(); From 07081d52fe78c19c017d3b17a18658295a6b9094 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 24 Mar 2023 18:07:26 +0000 Subject: [PATCH 026/115] Change dataTransferred variable name --- src/lib/pipeline/LoadStoreQueue.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index 742e3bc791..6c7ebdc195 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -374,7 +374,7 @@ void LoadStoreQueue::tick() { // requests per cycle // Index 0: loads, index 1: stores std::array reqCounts = {0, 0}; - std::array dataTransfered = {0, 0}; + std::array dataTransferred = {0, 0}; std::array exceededLimits = {false, false}; auto itLoad = requestLoadQueue_.begin(); auto itStore = requestStoreQueue_.begin(); @@ -449,8 +449,8 @@ void LoadStoreQueue::tick() { assert(req.size <= bandwidth && "Individual memory request from LoadStoreQueue exceeds L1 " "bandwidth set and thus will never be submitted"); - dataTransfered[isStore] += req.size; - if (dataTransfered[isStore] > bandwidth) { + dataTransferred[isStore] += req.size; + if (dataTransferred[isStore] > bandwidth) { // No more requests can be scheduled this cycle exceededLimits[isStore] = true; itInsn = itReq->second.end(); From 382d1d75af034f70646bbaa49201349334b85aeb Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Mar 2023 14:40:59 +0100 Subject: [PATCH 027/115] Minor comment updates --- src/include/simeng/arch/riscv/Architecture.hh | 2 + src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/riscv/Architecture.cc | 2 - src/lib/arch/riscv/Instruction_decode.cc | 110 +----------------- src/lib/arch/riscv/Instruction_execute.cc | 50 ++------ test/regression/riscv/RISCVRegressionTest.hh | 2 +- 6 files changed, 17 insertions(+), 151 deletions(-) diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index e2b3af3e6c..87c6236735 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -14,6 +14,8 @@ namespace simeng { namespace arch { namespace riscv { +// A temporary enum to hold system register addresses +// TODO this should be removed upon relevant capstone updates typedef enum riscv_sysreg { RISCV_SYSREG_FFLAGS = 0x001, RISCV_SYSREG_FRM = 0x002, diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 0470713e99..18d6a32d46 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -243,7 +243,7 @@ class Instruction : public simeng::Instruction { bool isCompare_ = false; /** Is this a floating point operation? */ bool isFloat_ = false; - /** Is this a floating point to integer convert operation? */ + /** Is this a floating point <-> integer convert operation? */ bool isConvert_ = false; // Memory diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 8adc7e571f..d2450cb3da 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -105,8 +105,6 @@ Architecture::Architecture(kernel::Linux& kernel, YAML::Node config) for (size_t j = 0; j < group_node.size(); j++) { uint16_t group = group_node[j].as(); uint8_t newPort = static_cast(i); - // std::cerr << "group: " << group << " port: " << (int)newPort - // << std::endl; groupExecutionInfo_[group].ports.push_back(newPort); // Add inherited support for those appropriate groups diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index c9177b7c50..4666a8befa 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -58,115 +58,7 @@ Register csRegToRegister(unsigned int reg) { instructions tripping assertions. TODO remove once all extensions are supported*/ void Instruction::invalidateIfNotImplemented() { - if (metadata.opcode >= Opcode::RISCV_ADD && - metadata.opcode <= Opcode::RISCV_BNE) - return; - if (metadata.opcode >= Opcode::RISCV_DIV && - metadata.opcode <= Opcode::RISCV_ECALL) - return; - if (metadata.opcode >= Opcode::RISCV_JAL && - metadata.opcode <= Opcode::RISCV_SD) - return; - if (metadata.opcode >= Opcode::RISCV_SH && - metadata.opcode <= Opcode::RISCV_SRAW) - return; - if (metadata.opcode >= Opcode::RISCV_SRL && - metadata.opcode <= Opcode::RISCV_SW) - return; - if (metadata.opcode >= Opcode::RISCV_XOR && - metadata.opcode <= Opcode::RISCV_XORI) - return; - if (metadata.opcode == Opcode::RISCV_FENCE) return; - if (metadata.opcode >= Opcode::RISCV_CSRRC && - metadata.opcode <= Opcode::RISCV_CSRRWI) - return; - - if (metadata.opcode >= Opcode::RISCV_FADD_D && - metadata.opcode <= Opcode::RISCV_FADD_S) - return; - - if (metadata.opcode >= Opcode::RISCV_FCVT_D_L && - metadata.opcode <= Opcode::RISCV_FDIV_S) - return; - - if (metadata.opcode >= Opcode::RISCV_FEQ_D && - metadata.opcode <= Opcode::RISCV_FSW) - return; - - // if (metadata.opcode == Opcode::RISCV_FSD) return; - // if (metadata.opcode == Opcode::RISCV_FSW) return; - // if (metadata.opcode == Opcode::RISCV_FLD) return; - // if (metadata.opcode == Opcode::RISCV_FLW) return; - // - // if (metadata.opcode == Opcode::RISCV_FADD_D) return; - // if (metadata.opcode == Opcode::RISCV_FADD_S) return; - // if (metadata.opcode == Opcode::RISCV_FSUB_D) return; - // if (metadata.opcode == Opcode::RISCV_FSUB_S) return; - // if (metadata.opcode == Opcode::RISCV_FDIV_D) return; - // if (metadata.opcode == Opcode::RISCV_FDIV_S) return; - // if (metadata.opcode == Opcode::RISCV_FMUL_D) return; - // if (metadata.opcode == Opcode::RISCV_FMUL_S) return; - // if (metadata.opcode == Opcode::RISCV_FSQRT_D) return; - // if (metadata.opcode == Opcode::RISCV_FSQRT_S) return; - // - // if (metadata.opcode == Opcode::RISCV_FMIN_D) return; - // if (metadata.opcode == Opcode::RISCV_FMIN_S) return; - // if (metadata.opcode == Opcode::RISCV_FMAX_D) return; - // if (metadata.opcode == Opcode::RISCV_FMAX_S) return; - // - // if (metadata.opcode == Opcode::RISCV_FMADD_D) return; - // if (metadata.opcode == Opcode::RISCV_FMADD_S) return; - // if (metadata.opcode == Opcode::RISCV_FNMADD_D) return; - // if (metadata.opcode == Opcode::RISCV_FNMADD_S) return; - // if (metadata.opcode == Opcode::RISCV_FNMSUB_D) return; - // if (metadata.opcode == Opcode::RISCV_FNMSUB_S) return; - // if (metadata.opcode == Opcode::RISCV_FMSUB_S) return; - // if (metadata.opcode == Opcode::RISCV_FMSUB_D) return; - // - // if (metadata.opcode == Opcode::RISCV_FCVT_D_L) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_D_W) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_S_L) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_S_W) return; - // - // if (metadata.opcode == Opcode::RISCV_FCVT_W_D) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_W_S) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_L_D) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_L_S) return; - // - // if (metadata.opcode == Opcode::RISCV_FCVT_WU_D) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_WU_S) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_LU_D) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_LU_S) return; - // - // if (metadata.opcode == Opcode::RISCV_FCVT_D_WU) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_S_WU) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_D_LU) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_S_LU) return; - // - // if (metadata.opcode == Opcode::RISCV_FCVT_D_S) return; - // if (metadata.opcode == Opcode::RISCV_FCVT_S_D) return; - // - // if (metadata.opcode == Opcode::RISCV_FSGNJ_D) return; - // if (metadata.opcode == Opcode::RISCV_FSGNJ_S) return; - // if (metadata.opcode == Opcode::RISCV_FSGNJN_S) return; - // if (metadata.opcode == Opcode::RISCV_FSGNJN_D) return; - // if (metadata.opcode == Opcode::RISCV_FSGNJX_D) return; - // if (metadata.opcode == Opcode::RISCV_FSGNJX_S) return; - // - // if (metadata.opcode == Opcode::RISCV_FMV_X_D) return; - // if (metadata.opcode == Opcode::RISCV_FMV_X_W) return; - // if (metadata.opcode == Opcode::RISCV_FMV_D_X) return; - // if (metadata.opcode == Opcode::RISCV_FMV_W_X) return; - // - // if (metadata.opcode == Opcode::RISCV_FEQ_D) return; - // if (metadata.opcode == Opcode::RISCV_FEQ_S) return; - // if (metadata.opcode == Opcode::RISCV_FLT_D) return; - // if (metadata.opcode == Opcode::RISCV_FLT_S) return; - // if (metadata.opcode == Opcode::RISCV_FLE_D) return; - // if (metadata.opcode == Opcode::RISCV_FLE_S) return; - - // std::cout << "[SimEng:RISC-V:Decode] Insn: " << metadata.mnemonic << " " - // << metadata.operandStr << std::endl; + return; exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 7ee7d30432..31e8fbe550 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -842,7 +842,7 @@ void Instruction::execute() { } // Control and Status Register extension (Zicsr) - // Do not read-modify-write ATOMICALLY + // Currently do not read-modify-write ATOMICALLY // Left unimplemented due to Capstone being unable to disassemble CSR // addresses case Opcode::RISCV_CSRRW: { // CSRRW rd,csr,rs1 @@ -892,9 +892,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_CSRRS: { // CSRRS rd,csr,rs1 - // dummy implementation only used by floating point frflags, needs - // capstone update to recognise system registers. No update of system - // register as rs1 == zero + // dummy implementation needs capstone update to recognise system + // registers results[0] = RegisterValue(static_cast(0), 8); break; @@ -912,12 +911,15 @@ void Instruction::execute() { break; } - // TODO Apart from transfer operations described in the previous - // paragraph, all other floating-point operations on narrower n-bit - // operations, n < FLEN, check if the input operands are correctly - // NaN-boxed, i.e., all upper FLEN−n bits are 1. If so, the n - // least-significant bits of the input are used as the input value, - // otherwise the input value is treated as an n-bit canonical NaN. + // TODO "Apart from transfer operations ... all other floating-point + // operations on narrower n-bit operations, n < FLEN, check if the input + // operands are correctly NaN-boxed, i.e., all upper FLEN−n bits are 1. If + // so, the n least-significant bits of the input are used as the input + // value, otherwise the input value is treated as an n-bit canonical NaN." + + // TODO need to take rounding mode into account as these can be set per + // instruction https://en.cppreference.com/w/cpp/numeric/fenv/FE_round + // std::fesetround(FE_TONEAREST); // Single-Precision Floating-Point (F) // Double-Precision Floating-Point (D) @@ -936,7 +938,6 @@ void Instruction::execute() { } case Opcode::RISCV_FLW: { // FLW rd,rs1,imm // Note: elements of memory data are RegisterValue's - // Get as uint32 to allow for NaN boxing const float memSingle = memoryData[0].get(); results[0] = RegisterValue(NanBoxFloat(memSingle), 8); @@ -1151,7 +1152,6 @@ void Instruction::execute() { results[0] = RegisterValue(NanBoxFloat(-(rs1 * rs2) - rs3), 8); break; } - case Opcode::RISCV_FCVT_D_L: { // FCVT.D.L rd,rs1 const int64_t rs1 = operands[0].get(); @@ -1177,9 +1177,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_W_D: { // FCVT.W.D rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TONEAREST); const double rs1 = std::rint(operands[0].get()); if (std::isnan(rs1)) { @@ -1190,9 +1187,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_W_S: { // FCVT.W.S rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const float rs1 = operands[0].get(); if (std::isnan(rs1)) { @@ -1203,9 +1197,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_L_D: { // FCVT.L.D rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TONEAREST); const double rs1 = std::rint(operands[0].get()); if (std::isnan(rs1)) { @@ -1216,9 +1207,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_L_S: { // FCVT.L.S rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const float rs1 = operands[0].get(); if (std::isnan(rs1)) { @@ -1229,10 +1217,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_WU_D: { // FCVT.WU.D rd,rs1 - // TODO need to take rounding mode into - // account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const double rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { @@ -1248,10 +1232,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_WU_S: { // FCVT.WU.S rd,rs1 - // TODO need to take rounding mode into - // account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const float rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { @@ -1267,9 +1247,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_LU_D: { // FCVT.LU.D rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const double rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { @@ -1285,9 +1262,6 @@ void Instruction::execute() { break; } case Opcode::RISCV_FCVT_LU_S: { // FCVT.LU.S rd,rs1 - // TODO need to take rounding mode into account, +- INF - // https://en.cppreference.com/w/cpp/numeric/fenv/FE_round - // std::fesetround(FE_TOWARDZERO); const float rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index d625614016..514f86f84f 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -81,7 +81,7 @@ class RISCVRegressionTest : public RegressionTest { return getRegister({simeng::arch::riscv::RegisterType::GENERAL, tag}); } - /** Get the value of a floating point purpose register. */ + /** Get the value of a floating point register. */ template T getFPRegister(uint8_t tag) const { return getRegister({simeng::arch::riscv::RegisterType::FLOAT, tag}); From f4299b662674a975774c2841a7aa09549d3d9fc6 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Mar 2023 15:51:58 +0100 Subject: [PATCH 028/115] Update CSR dummy test and add pseudoinstruction --- src/lib/arch/riscv/InstructionMetadata.cc | 11 +++++++++-- src/lib/arch/riscv/Instruction_execute.cc | 1 + test/regression/riscv/instructions/csr.cc | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 78527f17e5..f23e35d4ad 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -339,8 +339,15 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[1].reg = RISCV_SYSREG_FRM; // frm address operandCount = 3; - } else if (strcmp(mnemonic, "fsrm") == 0) { - assert(false && "Unimplemented psuedoinstruction fsrm"); + } else if (operandCount == 2 && strcmp(mnemonic, "fsrm") == 0) { + // fsrm R1, R2 is pseudo of CSRRW R1, frm, R2 (Write FP rounding mode) + // CSRRW R1, R2, _ -> CSRRW R1, frm, R2 + operands[2] = operands[1]; + + operands[1].type = RISCV_OP_IMM; + operands[1].reg = RISCV_SYSREG_FRM; + + operandCount = 3; } break; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 31e8fbe550..f70c5bec66 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -885,6 +885,7 @@ void Instruction::execute() { // " // << metadata.operands[1].reg << std::endl; } + results[0] = RegisterValue(0, 8); break; } case Opcode::RISCV_CSRRWI: { // CSRRWI rd,csr,imm diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index 72a2d9a602..28d3f99a5f 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -4,9 +4,9 @@ namespace { using InstCsr = RISCVRegressionTest; -TEST_P(InstCsr, jalr) { +TEST_P(InstCsr, cycle) { RUN_RISCV(R"( - #csrrw t1, cycle, t1 + csrrw t1, frm, t1 )"); } From 8dc8957993dd43a0d4fba1ad2a4d05dbbd93db63 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Mar 2023 16:10:18 +0100 Subject: [PATCH 029/115] Remove temporary mremap implementation --- src/include/simeng/kernel/Linux.hh | 4 --- src/lib/arch/riscv/ExceptionHandler.cc | 30 ----------------- src/lib/kernel/Linux.cc | 45 -------------------------- 3 files changed, 79 deletions(-) diff --git a/src/include/simeng/kernel/Linux.hh b/src/include/simeng/kernel/Linux.hh index 5292ecd03d..0908d59006 100644 --- a/src/include/simeng/kernel/Linux.hh +++ b/src/include/simeng/kernel/Linux.hh @@ -196,10 +196,6 @@ class Linux { /** munmap syscall: deletes the mappings for the specified address range. */ int64_t munmap(uint64_t addr, size_t length); - /** mremap syscall: expand memory mapping */ - uint64_t mremap(uint64_t oid_address, size_t old_size, size_t new_size, - int flags, uint64_t new_address); - /** mmap syscall: map files or devices into memory. */ uint64_t mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset); diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index 5f063f07ea..7d2a185c5b 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -565,32 +565,6 @@ bool ExceptionHandler::init() { stateChange = {ChangeType::REPLACEMENT, {R0}, {result}}; break; } - case 216: { // mremap - uint64_t old_address = registerFileSet.get(R0).get(); - size_t old_size = registerFileSet.get(R1).get(); - size_t new_size = registerFileSet.get(R2).get(); - int flags = registerFileSet.get(R3).get(); - uint64_t new_address = registerFileSet.get(R4).get(); - - // Currently only MAYMOVE supported - if (flags == 1) { - uint64_t result = linux_.mremap(old_address, old_size, new_size, - flags, new_address); - if (result == -1) { - stateChange = { - ChangeType::REPLACEMENT, {R0}, {static_cast(-1)}}; - } else { - stateChange = {ChangeType::REPLACEMENT, {R0}, {result}}; - } - } else { - printException(instruction_); - std::cout << "Unsupported arguments for syscall: " << syscallId - << std::endl; - return fatal(); - } - - break; - } case 222: { // mmap uint64_t addr = registerFileSet.get(R0).get(); size_t length = registerFileSet.get(R1).get(); @@ -659,10 +633,6 @@ bool ExceptionHandler::init() { stateChange = {ChangeType::REPLACEMENT, {R0}, {0ull}}; break; } - case 1024: { - std::cout << "SIMENG: BROKEN SYSCALL 1024" << std::endl; - break; - } default: printException(instruction_); std::cout << "\n[SimEng:ExceptionHandler] Unrecognised syscall: " diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index 991c678e46..9f0b594114 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -403,51 +403,6 @@ int64_t Linux::munmap(uint64_t addr, size_t length) { return 0; } -// TODO needs tests -uint64_t Linux::mremap(uint64_t old_address, size_t old_size, size_t new_size, - int flags, uint64_t new_address) { - LinuxProcessState* lps = &processStates_[0]; - bool MAYMOVE = flags & 1; - bool FIXED = flags & 2; - bool DONTUNMAP = flags & 4; - - // Check old address page alignment - assert(old_address == alignToBoundary(old_address, lps->pageSize) && - "mremap: old_address does not align to page boundary"); - - if (lps->contiguousAllocations.size() > 1) { - for (auto& alloc : lps->contiguousAllocations) { - // Find allocation with old_address - if (alloc.vm_start == old_address) { - // TODO If the value of old_size is zero, and old_address refers to a - // shareable mapping (see mmap(2) MAP_SHARED), then mremap() will create - // a new mapping of the same pages - - // If extended mapping will fit in the current gap - if ((alloc.vm_next->vm_start - alloc.vm_start) >= new_size) { - alloc.vm_end = alloc.vm_start + new_size; - return old_address; - } else if (MAYMOVE) { - // TODO change links - return mmap(0, new_size, -1, 34, -1, 0); - } - } - } - } else if (lps->contiguousAllocations.size() > 0) { - if (lps->contiguousAllocations[0].vm_start == old_address) { - auto& alloc = lps->contiguousAllocations[0]; - alloc.vm_end = alloc.vm_start + new_size; - return alloc.vm_start; - } else { - // old_address does not point to the one current allocation, MAP_FAILED - return -1; - } - } - - // No allocations, MAP_FAILED - return -1; -} - uint64_t Linux::mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset) { LinuxProcessState* lps = &processStates_[0]; From 218416e28300b893c5f662c81c4db067a8c5fb60 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 27 Mar 2023 16:29:56 +0100 Subject: [PATCH 030/115] Change cout to cerr --- src/lib/Elf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Elf.cc b/src/lib/Elf.cc index 6a2e71aba3..28b138558b 100644 --- a/src/lib/Elf.cc +++ b/src/lib/Elf.cc @@ -37,7 +37,7 @@ Elf::Elf(std::string path, char** imagePointer) { char fileMagic[4]; file.read(fileMagic, 4); if (std::memcmp(elfMagic, fileMagic, sizeof(elfMagic))) { - std::cout << "[SimEng:Elf] Elf magic does not match" << std::endl; + std::cerr << "[SimEng:Elf] Elf magic does not match" << std::endl; return; } @@ -50,7 +50,7 @@ Elf::Elf(std::string path, char** imagePointer) { char bitFormat; file.read(&bitFormat, sizeof(bitFormat)); if (bitFormat != ElfBitFormat::Format64) { - std::cout << "[SimEng:Elf] Unsupported architecture detected in Elf" + std::cerr << "[SimEng:Elf] Unsupported architecture detected in Elf" << std::endl; return; } From d90884358b5eff75f48059b6794a3cc9d69c9ebe Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 31 Mar 2023 13:06:54 +0100 Subject: [PATCH 031/115] Update branch prediction supplying logic --- src/lib/pipeline/FetchUnit.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index ade3d307c0..0f3551fe17 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -141,12 +141,21 @@ void FetchUnit::tick() { {encoding, bytesRead, pc_, macroOp[0]->getBranchPrediction()}); if (pc_ == loopBoundaryAddress_) { - // loopBoundaryAddress_ has been fetched whilst filling the loop buffer. - // Stop filling as loop body has been recorded and begin to supply - // decode unit with instructions from the loop buffer - loopBufferState_ = LoopBufferState::SUPPLYING; - bufferedBytes_ = 0; - break; + if (macroOp[0]->isBranch() && + !macroOp[0]->getBranchPrediction().taken) { + // loopBoundaryAddress_ has been fetched whilst filling the loop + // buffer BUT this is a branch, predicted to branch out of the loop + // being buffered. Stop filling the loop buffer and don't supply to + // decode + loopBufferState_ = LoopBufferState::IDLE; + } else { + // loopBoundaryAddress_ has been fetched whilst filling the loop + // buffer. Stop filling as loop body has been recorded and begin to + // supply decode unit with instructions from the loop buffer + loopBufferState_ = LoopBufferState::SUPPLYING; + bufferedBytes_ = 0; + break; + } } } else if (loopBufferState_ == LoopBufferState::WAITING && pc_ == loopBoundaryAddress_) { From 1cc2bcde324a4ec37aed56499cdb770f6d3f9f4a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 17 Jul 2023 13:28:32 +0100 Subject: [PATCH 032/115] Change ticks to uint to reduce chance of overflow --- src/tools/simeng/main.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/simeng/main.cc b/src/tools/simeng/main.cc index fa9b58baa1..ae8a95abd2 100644 --- a/src/tools/simeng/main.cc +++ b/src/tools/simeng/main.cc @@ -10,8 +10,8 @@ #include "simeng/version.hh" /** Tick the provided core model until it halts. */ -int simulate(simeng::Core& core, simeng::MemoryInterface& dataMemory, - simeng::MemoryInterface& instructionMemory) { +uint64_t simulate(simeng::Core& core, simeng::MemoryInterface& dataMemory, + simeng::MemoryInterface& instructionMemory) { uint64_t iterations = 0; // Tick the core and memory interfaces until the program has halted @@ -91,7 +91,7 @@ int main(int argc, char** argv) { // Run simulation std::cout << "[SimEng] Starting...\n" << std::endl; - int iterations = 0; + uint64_t iterations = 0; auto startTime = std::chrono::high_resolution_clock::now(); iterations = simulate(*core, *dataMemory, *instructionMemory); From 1ba1d53df21aa80335484c1eac219318f17e9fb3 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 18 Jul 2023 17:35:06 +0100 Subject: [PATCH 033/115] Remove empty_ from execute unit after merge --- src/lib/pipeline/ExecuteUnit.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index 9625ec4bd5..7d789b34bd 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -28,7 +28,6 @@ ExecuteUnit::ExecuteUnit( void ExecuteUnit::tick() { tickCounter_++; shouldFlush_ = false; - empty_ = false; if (stallUntil_ <= tickCounter_) { input_.stall(false); @@ -162,7 +161,6 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { forwardOperands_(uop->getDestinationRegisters(), uop->getResults()); output_.getTailSlots()[0] = std::move(uop); - empty_ = true; } bool ExecuteUnit::shouldFlush() const { return shouldFlush_; } @@ -225,7 +223,6 @@ uint64_t ExecuteUnit::getBranchMispredictedCount() const { } uint64_t ExecuteUnit::getCycles() const { return cycles_; } -bool ExecuteUnit::isEmpty() const { return empty_; } bool ExecuteUnit::isEmpty() const { // Execution unit is considered empty if no instructions are present in the From b4ac39b0704b7e825f6f0987a5b314df19993edb Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 25 Oct 2023 15:07:56 +0100 Subject: [PATCH 034/115] Implement first C instructions, enough to run gcc 12.2 STREAM --- src/include/simeng/arch/riscv/Architecture.hh | 21 + src/include/simeng/arch/riscv/Instruction.hh | 6 + src/lib/arch/riscv/Architecture.cc | 30 +- src/lib/arch/riscv/Instruction.cc | 2 + src/lib/arch/riscv/InstructionMetadata.cc | 418 +++++++++++++++++- src/lib/arch/riscv/InstructionMetadata.hh | 12 + src/lib/arch/riscv/Instruction_address.cc | 32 ++ src/lib/arch/riscv/Instruction_execute.cc | 30 +- 8 files changed, 536 insertions(+), 15 deletions(-) diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 87c6236735..64c943ca83 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -14,6 +14,21 @@ namespace simeng { namespace arch { namespace riscv { +struct constantsPool { + const uint8_t alignMask = 0x3; + const uint8_t alignMaskCompressed = 0x1; + const uint8_t bytesLimit = 4; + const uint8_t bytesLimitCompressed = 2; + const uint8_t byteLength64 = 8; + const uint8_t byteLength32 = 4; +}; + +struct archConstants { + uint8_t alignMask; + uint8_t bytesLimit; /* Minimum bytes the decoder needs to process */ + uint8_t regWidth; /* Register width in bytes */ +}; + // A temporary enum to hold system register addresses // TODO this should be removed upon relevant capstone updates typedef enum riscv_sysreg { @@ -77,6 +92,9 @@ class Architecture : public arch::Architecture { std::vector getConfigPhysicalRegisterQuantities( YAML::Node config) const override; + /** Return a struct contains constants */ + archConstants getConstants() const; + private: /** Retrieve an executionInfo object for the requested instruction. If a * opcode-based override has been defined for the latency and/or @@ -115,6 +133,9 @@ class Architecture : public arch::Architecture { /** System Register of Processor Retired Counter. */ simeng::Register retiredSystemReg_; + + /** A struct contains constants */ + archConstants constants_; }; } // namespace riscv diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 7c3994730e..edf6bc170d 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -166,6 +166,9 @@ class Instruction : public simeng::Instruction { * automatically supplied as zero. */ static const Register ZERO_REGISTER; + static const Register RA_REGISTER; + static const Register SP_REGISTER; + private: /** The maximum number of source registers any supported RISC-V instruction * can have. */ @@ -246,6 +249,9 @@ class Instruction : public simeng::Instruction { /** Is this a floating point <-> integer convert operation? */ bool isConvert_ = false; + /** Extracted value of current immediate from metadata */ + uint32_t c_imm = 0; + // Memory /** Set the accessed memory addresses, and create a corresponding memory data * vector. */ diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index d2450cb3da..5e65284b5a 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -16,7 +16,20 @@ std::forward_list Architecture::metadataCache; Architecture::Architecture(kernel::Linux& kernel, YAML::Node config) : linux_(kernel) { - cs_err n = cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64, &capstoneHandle); + cs_mode csMode = CS_MODE_RISCV64; + constantsPool constantsPool; + + // TODO if here to check if compressed instructions are allowed based off of + // config options + + constants_.alignMask = constantsPool.alignMaskCompressed; + constants_.regWidth = constantsPool.byteLength64; + constants_.bytesLimit = constantsPool.bytesLimitCompressed; + + cs_err n = cs_open(CS_ARCH_RISCV, + static_cast(CS_MODE_RISCV64 | CS_MODE_RISCVC), + &capstoneHandle); + if (n != CS_ERR_OK) { std::cerr << "[SimEng:Architecture] Could not create capstone handle due " "to error " @@ -146,8 +159,11 @@ Architecture::~Architecture() { uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { + // std::cerr << std::hex << instructionAddress << std::dec; + // Check that instruction address is 4-byte aligned as required by RISC-V - if (instructionAddress & 0x3) { + // 2-byte when Compressed ISA is supported + if (instructionAddress & constants_.alignMask) { // Consume 1-byte and raise a misaligned PC exception auto metadata = InstructionMetadata((uint8_t*)ptr, 1); metadataCache.emplace_front(metadata); @@ -160,8 +176,10 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, return 1; } - assert(bytesAvailable >= 4 && - "Fewer than 4 bytes supplied to RISC-V decoder"); + assert(bytesAvailable >= constants_.bytesLimit && + "Fewer than bytes limit supplied to RISC-V decoder"); + + // TODO should this still be 4 bytes?? Seems to work as is // Dereference the instruction pointer to obtain the instruction word uint32_t insn; @@ -205,7 +223,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uop->setInstructionAddress(instructionAddress); - return 4; + return iter->second.getMetadata().lenBytes; } executionInfo Architecture::getExecutionInfo(Instruction& insn) const { @@ -287,6 +305,8 @@ void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, regFile->set(retiredSystemReg_, retired); } +archConstants Architecture::getConstants() const { return constants_; } + } // namespace riscv } // namespace arch } // namespace simeng diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 597d98322a..4e33c28630 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -11,6 +11,8 @@ namespace arch { namespace riscv { const Register Instruction::ZERO_REGISTER = {RegisterType::GENERAL, 0}; +const Register Instruction::RA_REGISTER = {RegisterType::GENERAL, 1}; +const Register Instruction::SP_REGISTER = {RegisterType::GENERAL, 2}; Instruction::Instruction(const Architecture& architecture, const InstructionMetadata& metadata) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index f23e35d4ad..e92b7861d5 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -16,7 +16,11 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitSourceCount(insn.detail->regs_read_count), implicitDestinationCount(insn.detail->regs_write_count), operandCount(insn.detail->riscv.op_count) { - std::memcpy(encoding, insn.bytes, sizeof(encoding)); + // std::memcpy(encoding, insn.bytes, sizeof(encoding)); + setLength(insn.size); + std::memset(encoding, 0, 4); + std::memcpy(encoding, insn.bytes, insn.size); + // Copy printed output std::strncpy(mnemonic, insn.mnemonic, CS_MNEMONIC_SIZE); operandStr = std::string(insn.op_str); @@ -29,6 +33,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->riscv.operands, sizeof(cs_riscv_op) * operandCount); + convertCompressedInstruction(insn); alterPseudoInstructions(insn); } @@ -38,7 +43,8 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, opcode(Opcode::RISCV_INSTRUCTION_LIST_END), implicitSourceCount(0), implicitDestinationCount(0), - operandCount(0) { + operandCount(0), + len(INSTR_LENGTH::IL_INVALID) { assert(bytes <= sizeof(encoding)); std::memcpy(encoding, invalidEncoding, bytes); mnemonic[0] = '\0'; @@ -440,6 +446,414 @@ void InstructionMetadata::includeZeroRegisterPosZero() { operandCount = 3; } +void InstructionMetadata::duplicateFirstOp() { + // Given register sequence {Op_a, Op_b, _} return {Op_a, Op_a, Op_b} + operands[2] = operands[1]; + operands[1] = operands[0]; + + operandCount = 3; +} + +void InstructionMetadata::createMemOpPosOne() { + // Given register sequence {Op_a, imm, reg} return {Op_a, mem, _} + assert(operands[1].type == RISCV_OP_IMM && + "Incorrect operand type when creating memory operand"); + assert(operands[2].type == RISCV_OP_REG && + "Incorrect operand type when creating memory operand"); + + cs_riscv_op temp; + temp.type = RISCV_OP_MEM; + temp.imm = operands[1].imm; // + temp.mem.base = operands[2].reg; + temp.mem.disp = operands[1].imm; + + operands[1] = temp; + + operandCount = 2; +} + +void InstructionMetadata::setLength(uint8_t size) { + lenBytes = size; + switch (size) { + case 2: + len = INSTR_LENGTH::IL_16B; + break; + case 4: + len = INSTR_LENGTH::IL_32B; + break; + default: + len = INSTR_LENGTH::IL_INVALID; + } +} +void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { + // std::cerr << ": " << insn.mnemonic << " " << operandStr << std::endl; + if (len != INSTR_LENGTH::IL_16B) { + return; + } + + // std::cerr << std::endl + // << "COMPRESSED:: " << insn.address << ":" << insn.mnemonic << " + // " + // << operandStr << std::endl; + + switch (insn.opcode) { + case Opcode::RISCV_C_JR: + // jalr x0, 0(rs1) + // trap if rs1 = zero + opcode = Opcode::RISCV_JALR; + // TODO repeat logic so that mnemonic can remain for help when debugging + // Change mnemonic to allow pseudoinstruction code to work + strcpy(mnemonic, reinterpret_cast("jr")); + break; + case Opcode::RISCV_C_MV: + // add rd, x0, rs2 + // trap if rs2 = zero. rs2 == zero corresponds to C.JR + // rs2==zero and rd == zero are hints + // C.MV rd, rs2, _ -> ADD rd, zero, rs2 + opcode = Opcode::RISCV_ADD; + + includeZeroRegisterPosOne(); + + // operands[2] = insn.detail->riscv.operands[1]; + // + // operands[1].type = RISCV_OP_REG; + // operands[1].reg = 1; + // + // operandCount = 3; + break; + case Opcode::RISCV_C_LDSP: { + // TODO valid for RV64 only. Make this check + // ld rd, offset[8:3](x2) + // offset is immediate scaled by 8 + // trap if rd=zero + opcode = Opcode::RISCV_LD; + + // Create operand formatted like LD instruction + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_ADDI4SPN: + // addi rd ′ , x2, nzuimm[9:2] + // trap if nzuimm=zero + opcode = Opcode::RISCV_ADDI; + // All operands correct + break; + case Opcode::RISCV_C_LI: + // addi rd, x0, imm[5:0] + // trap if rd=zero + // C.LI rd, imm, _ -> addi rd, zero, imm + opcode = Opcode::RISCV_ADDI; + + includeZeroRegisterPosOne(); + + // operands[2] = insn.detail->riscv.operands[1]; + // + // operands[1].type = RISCV_OP_REG; + // operands[1].reg = 1; + // + // operandCount = 3; + + break; + case Opcode::RISCV_C_ADDI16SP: + // Opcode shared with C.LUI but has Rd = x2 + // addi x2, x2, nzimm[9:4] + // trap if nzimm=zero + // C.ADDI16SP sp, imm, _ -> addi sp, sp, imm + opcode = Opcode::RISCV_ADDI; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_SLLI: + // slli rd, rd, shamt[5:0] + // + // For RV32C, shamt[5] must be zero; the code points with shamt[5]=1 are + // reserved for custom extensions. For RV32C and RV64C, the shift amount + // must be non-zero; the code points with shamt=0 are HINTs. For all base + // ISAs, the code points with rd=x0 are HINTs, except those with + // shamt[5]=1 in RV32C. + + // C.SLLI rd, shamt, _ -> slli rd, rd, shamt + + opcode = Opcode::RISCV_SLLI; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_SDSP: { + // TODO rv64 ONLY, make check for this + // sd rs2, offset[8:3](x2) + + opcode = Opcode::RISCV_SD; + + // Create operand formatted like SD instruction + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_ADD: + // add rd, rd, rs2 + // trap if rs2 = zero + // code points with rs2=x0 correspond + // to the C.JALR and C.EBREAK + // instructions. The code points with + // rs2̸=x0 and rd=x0 are HINTs. + // C.ADD rd, rs2, _ -> add rd, rd, rs2 + + opcode = Opcode::RISCV_ADD; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_LD: { + // TODO rv64 ONLY, make check for this + // ld rd ′ , offset[7:3](rs1 ′) + + opcode = Opcode::RISCV_LD; + + // Create operand formatted like LD instruction + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_ADDI: { + // addi rd, rd, nzimm[5:0] + // trap if rd=zero and imm=zero + // C.ADDI rd, imm, _ -> addi rd, rd, imm + + opcode = Opcode::RISCV_ADDI; + + duplicateFirstOp(); + + break; + } + case Opcode::RISCV_C_BNEZ: + // bne rs1 ′ , x0, offset[8:1] + // C.BNEZ rs1, imm, _ -> bne rs1, zero, imm + opcode = Opcode::RISCV_BNE; + + includeZeroRegisterPosOne(); + + break; + case Opcode::RISCV_C_SD: { + // TODO rv64 ONLY, make check for this + // sd rs2 ′ , offset[7:3](rs1 ′) + + opcode = Opcode::RISCV_SD; + // Create operand formatted like SD instruction + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_BEQZ: + // beq rs1 ′ , x0, offset[8:1] + // C.BEQZ rs1, imm, _ -> beq rs1, zero, imm + opcode = Opcode::RISCV_BEQ; + + includeZeroRegisterPosOne(); + + break; + case Opcode::RISCV_C_ANDI: + // andi rd ′, rd ′ , imm[5:0] + // C.ANDI rd, imm, _ -> andi rd, rd, imm + opcode = Opcode::RISCV_ANDI; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_LUI: + // lui rd, nzimm[17:12] + // trap if rd = x0/x2, imm = 0 + opcode = Opcode::RISCV_LUI; + // all operands correct + break; + case Opcode::RISCV_C_LWSP: { + // lw rd, offset[7:2](x2) + opcode = Opcode::RISCV_LW; + + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_SW: { + // sw rs2 ′, offset[6:2](rs1 ′) + + opcode = Opcode::RISCV_SW; + + createMemOpPosOne(); + + break; + } + case Opcode::RISCV_C_J: + // jal x0, offset[11:1] + // C.J imm, _ -> jal zero, imm + opcode = Opcode::RISCV_JAL; + + operands[1] = operands[0]; + + operands[0].type = RISCV_OP_REG; + operands[0].reg = 1; + + break; + case Opcode::RISCV_C_ADDIW: + // TODO rv64 ONLY, make check for this + // addiw rd, rd, imm[5:0] + // trap if rd = zero + // C.ADDIW rd, imm, _ -> addiw rd, rd, imm + opcode = Opcode::RISCV_ADDIW; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_SUB: + // sub rd ′ , rd ′ , rs2 ′ + // C.SUB rd, rs2, -> sub rd, rd, rs2 + opcode = Opcode::RISCV_SUB; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_LW: + // lw rd ′ , offset[6:2](rs1 ′ ) + + opcode = Opcode::RISCV_LW; + + createMemOpPosOne(); + + break; + + case Opcode::RISCV_C_SRLI: + // srli rd ′ , rd ′ , shamt[5:0] + // C.SRLI rd, imm, _ -> srli rd, rd, imm + + opcode = Opcode::RISCV_SRLI; + + duplicateFirstOp(); + + break; + + case Opcode::RISCV_C_ADDW: + // TODO rv64 ONLY, make check for this + // addw rd ′ , rd ′ , rs2 ′ + // C.ADDW rd, rs2, _ -> addw rd, rd, rs2 + opcode = Opcode::RISCV_ADDW; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_AND: + // and rd ′ , rd ′ , rs2 ′ + // C.AND rd, rs2, _ -> and rd, rd, rs2 + opcode = Opcode::RISCV_AND; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_OR: + // or rd ′ , rd ′ , rs2 ′ + // C.OR rd, rs2, _ -> or rd, rd, rs2 + + opcode = Opcode::RISCV_OR; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_JALR: + // jalr x1, 0(rs1) + // trap if rs1=zero + // C.JALR rs1, _, _ -> jalr x1, rs1, 0 + + opcode = Opcode::RISCV_JALR; + + operands[1] = operands[0]; + + operands[0].reg = 2; + + operands[2].type = RISCV_OP_IMM; + operands[2].imm = 0; + + operandCount = 3; + + break; + case Opcode::RISCV_C_XOR: + // xor rd ′ , rd ′ , rs2 ′ + // C.XOR rd, rs2, _ -> xor rd, rd, rs2 + + opcode = Opcode::RISCV_XOR; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_SRAI: + // srai rd ′ , rd ′ , shamt[5:0] + // C.SRAI rd, imm, _ -> srai rd, rd, imm + + opcode = Opcode::RISCV_SRAI; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_FSD: + // TODO rv64dc ONLY, make check for this + // fsd rs2 ′, offset[7:3](rs1 ′) + + opcode = Opcode::RISCV_FSD; + + createMemOpPosOne(); + + break; + case Opcode::RISCV_C_FLD: + // TODO rv64dc ONLY, make check for this + // fld rd ′, offset[7:3](rs1 ′) + + opcode = Opcode::RISCV_FLD; + + createMemOpPosOne(); + + break; + case Opcode::RISCV_C_FSDSP: + // TODO rv64dc ONLY, make check for this + // fsd rs2, offset[8:3](x2) + + opcode = Opcode::RISCV_FSD; + + createMemOpPosOne(); + + break; + case Opcode::RISCV_C_SUBW: + // TODO rv64 ONLY, make check for this + // subw rd ′ , rd ′ , rs2 ′ + // C.SUBW rd, rs2, _ -> subw rd, rd, rs2 + + opcode = Opcode::RISCV_SUBW; + + duplicateFirstOp(); + + break; + case Opcode::RISCV_C_NOP: + // nop + // C.NOP _, _, _-> addi x0, x0, 0 + opcode = Opcode::RISCV_ADDI; + + // Duplicate implementation of nop pseudoinstruction + operands[0].type = RISCV_OP_REG; + operands[0].reg = 1; + + operands[1].type = RISCV_OP_REG; + operands[1].reg = 1; + + operands[2].type = RISCV_OP_IMM; + operands[2].imm = 0; + + operandCount = 3; + + break; + default: + break; + } +} + } // namespace riscv } // namespace arch } // namespace simeng \ No newline at end of file diff --git a/src/lib/arch/riscv/InstructionMetadata.hh b/src/lib/arch/riscv/InstructionMetadata.hh index af5bebf815..57e3c71821 100644 --- a/src/lib/arch/riscv/InstructionMetadata.hh +++ b/src/lib/arch/riscv/InstructionMetadata.hh @@ -14,6 +14,8 @@ namespace Opcode { #include "RISCVGenInstrInfo.inc" } // namespace Opcode +enum class INSTR_LENGTH { IL_16B, IL_32B, IL_INVALID }; + /** A simplified RISC-V-only version of the Capstone instruction structure. */ struct InstructionMetadata { public: @@ -70,6 +72,10 @@ struct InstructionMetadata { /** The number of explicit operands. */ uint8_t operandCount; + /** The instruction length for variable instruction length support. */ + INSTR_LENGTH len; + uint8_t lenBytes; + private: /** Detect instruction aliases and update metadata to match the de-aliased * instruction. */ @@ -85,6 +91,12 @@ struct InstructionMetadata { /** RISC-V helper function * Use register zero as operands[0] and immediate value as operands[2] */ void includeZeroRegisterPosZero(); + + /** Set the byte length of instruction */ + void setLength(uint8_t size); + void convertCompressedInstruction(const cs_insn& insn); + void duplicateFirstOp(); + void createMemOpPosOne(); }; } // namespace riscv diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 7000645bd6..80da6de036 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -1,4 +1,5 @@ #include +#include #include "InstructionMetadata.hh" #include "simeng/arch/riscv/Instruction.hh" @@ -14,10 +15,41 @@ span Instruction::generateAddresses() { uint64_t address; if (isLoad() && isStoreAddress() && isAtomic()) { // Atomics + // Metadata operand[2] corresponds to instruction operand[1] + assert(metadata.operands[2].type == RISCV_OP_REG && + "metadata operand not of correct type during RISC-V address " + "generation"); + address = operands[1].get(); + } else if (isLoad() && isAtomic()) { + // Load reserved + // Metadata operand[1] corresponds to instruction operand[0] + assert(metadata.operands[1].type == RISCV_OP_REG && + "metadata operand not of correct type during RISC-V address " + "generation"); + address = operands[0].get(); + } else if (isStoreAddress() && isAtomic()) { + // Store conditional + assert(metadata.operands[2].type == RISCV_OP_REG && + "metadata operand not of correct type during RISC-V address " + "generation"); address = operands[1].get(); } else if (isLoad()) { + assert(metadata.operands[1].type == RISCV_OP_MEM && + "metadata operand not of correct type during RISC-V address " + "generation"); + // std::cerr << "base val: " << operands[0].get() + // << ", disp: " << metadata.operands[1].mem.disp << std::endl; + address = operands[0].get() + metadata.operands[1].mem.disp; } else { + // std::cerr << "mem disp: " << metadata.operands[1].mem.disp << + // std::endl; std::cerr << metadata.operands[1].type << std::endl; + + assert((metadata.operands[1].type == RISCV_OP_MEM) && + "metadata operand not of correct type during RISC-V address " + "generation"); + // TODO don't use metadata directly here, extract it into member instruction + // variable address = operands[1].get() + metadata.operands[1].mem.disp; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index f70c5bec66..6d3eb7ae39 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -378,7 +378,7 @@ void Instruction::execute() { metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -386,12 +386,17 @@ void Instruction::execute() { case Opcode::RISCV_BNE: { // BNE rs1,rs2,imm const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); + // std::cerr << rs1 << ", " << rs2 << ", " << + // metadata.operands[2].imm + // << std::endl; + if (rs1 != rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + // Increase by instruction size to account for compressed instructions + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -404,7 +409,7 @@ void Instruction::execute() { metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -417,7 +422,7 @@ void Instruction::execute() { metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -430,7 +435,7 @@ void Instruction::execute() { metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -443,7 +448,7 @@ void Instruction::execute() { metadata.operands[2].imm; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + 4; + branchAddress_ = instructionAddress_ + metadata.lenBytes; branchTaken_ = false; } break; @@ -452,7 +457,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + metadata.operands[1].imm; // Set LSB of result to 0 branchTaken_ = true; - results[0] = RegisterValue(instructionAddress_ + 4, 8); + results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm @@ -460,7 +465,7 @@ void Instruction::execute() { (operands[0].get() + metadata.operands[2].imm) & ~1; // Set LSB of result to 0 branchTaken_ = true; - results[0] = RegisterValue(instructionAddress_ + 4, 8); + results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; } // TODO EBREAK @@ -1480,6 +1485,15 @@ void Instruction::execute() { default: return executionNYI(); } + // std::cerr << "0x" << std::hex << instructionAddress_ << std::dec << ": " + // << metadata.mnemonic << " " << metadata.operandStr; + // if (results[0]) { + // uint64_t val = results[0].get(); + // + // std::cerr << " => " << val << std::endl; + // } else { + // std::cerr << std::endl; + // } } } // namespace riscv From 17f21a75b62afcd0fc2b028118a8624043f0236a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 14 Dec 2023 15:37:36 +0000 Subject: [PATCH 035/115] Fixup --- configs/DEMO_RISCV.yaml | 4 ++-- src/include/simeng/arch/Architecture.hh | 3 +-- src/include/simeng/arch/aarch64/Architecture.hh | 3 +-- src/lib/arch/aarch64/Architecture.cc | 3 +-- src/lib/models/emulation/Core.cc | 2 +- src/lib/models/inorder/Core.cc | 3 +-- src/lib/models/outoforder/Core.cc | 3 +-- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 515e39e7f6..62c015a7d6 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -5,7 +5,7 @@ Core: ISA: rv64 - Simulation-Mode: outoforder + Simulation-Mode: emulation Clock-Frequency: 2.5 # Timer-Frequency is in MHz. Timer-Frequency: 200 @@ -34,7 +34,7 @@ Branch-Predictor: RAS-entries: 5 Fallback-Static-Predictor: "Always-Taken" L1-Data-Memory: - Interface-Type: Fixed + Interface-Type: Flat L1-Instruction-Memory: Interface-Type: Flat LSQ-L1-Interface: diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 6758f9adfe..4dbe377587 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -108,8 +108,7 @@ class Architecture { /** Updates System registers of any system-based timers. */ virtual void updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations, - const uint64_t retired) const = 0; + const uint64_t iterations) const = 0; }; } // namespace arch diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index cbd5046c43..39d399dc7d 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -60,8 +60,7 @@ class Architecture : public arch::Architecture { /** Updates System registers of any system-based timers. */ void updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations, - const uint64_t retired) const override; + const uint64_t iterations) const override; /** Returns the physical register structure as defined within the config file */ diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index c53c4da5b9..b7680afa45 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -287,8 +287,7 @@ uint64_t Architecture::getVectorLength() const { return VL_; } uint64_t Architecture::getStreamingVectorLength() const { return SVL_; } void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, - const uint64_t iterations, - const uint64_t retired) const { + const uint64_t iterations) const { // Update the Processor Cycle Counter to total cycles completed. regFile->set(PCCreg_, iterations); // Update Virtual Counter Timer at correct frequency. diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index aa2833ef73..ce7873f22b 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -159,7 +159,7 @@ void Core::tick() { } execute(uop); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, ticks_); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); } void Core::execute(std::shared_ptr& uop) { diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index b73aebcc3c..64d602b200 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -106,8 +106,7 @@ void Core::tick() { } fetchUnit_.requestFromPC(); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, - writebackUnit_.getInstructionsWrittenCount()); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); } bool Core::hasHalted() const { diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index d810b0a4a2..e7516a14a3 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -164,8 +164,7 @@ void Core::tick() { flushIfNeeded(); fetchUnit_.requestFromPC(); - isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_, - writebackUnit_.getInstructionsWrittenCount()); + isa_.updateSystemTimerRegisters(®isterFileSet_, ticks_); } void Core::flushIfNeeded() { From 9fa7a7b893faee6d5b94a65291bf638b0575d037 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 15 Dec 2023 15:43:58 +0000 Subject: [PATCH 036/115] Create test file and add two more instructions --- src/lib/arch/riscv/InstructionMetadata.cc | 16 +++++++++++++ test/regression/riscv/CMakeLists.txt | 3 ++- test/regression/riscv/RISCVRegressionTest.cc | 2 +- .../riscv/instructions/compressed.cc | 24 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/regression/riscv/instructions/compressed.cc diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index b7ef6fc682..1f6ae082ea 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -594,6 +594,14 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; } + case Opcode::RISCV_C_SWSP: { + // sw rs2, offset[7:2](x2) + opcode = Opcode::RISCV_SW; + + createMemOpPosOne(); + + break; + } case Opcode::RISCV_C_ADD: // add rd, rd, rs2 // trap if rs2 = zero @@ -678,6 +686,14 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; } + case Opcode::RISCV_C_FLDSP: + // TODO RV32DC/RV64DC-only + // fld rd, offset[8:3](x2) + opcode = Opcode::RISCV_FLD; + + createMemOpPosOne(); + + break; case Opcode::RISCV_C_SW: { // sw rs2 ′, offset[6:2](rs1 ′) diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index f97441b867..4b39e35575 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -13,7 +13,8 @@ add_executable(regression-riscv instructions/branch.cc instructions/atomic.cc instructions/float.cc - ) + instructions/compressed.cc +) target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(regression-riscv regression-test-base) diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index 8e3527e8b5..8216667746 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -11,7 +11,7 @@ void RISCVRegressionTest::run(const char* source) { LLVMInitializeRISCVTargetMC(); LLVMInitializeRISCVAsmParser(); - RegressionTest::run(source, "riscv64", "+m,+a,+f,+d"); + RegressionTest::run(source, "riscv64", "+m,+a,+f,+d,+c"); } // TODO create yaml YAML::Node RISCVRegressionTest::generateConfig() const { diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc new file mode 100644 index 0000000000..c35e064ba5 --- /dev/null +++ b/test/regression/riscv/instructions/compressed.cc @@ -0,0 +1,24 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using InstCompressed = RISCVRegressionTest; + +TEST_P(InstCompressed, flwsp) { + RUN_RISCV(R"( + c.fldsp fa5, 24(x2) + )"); +} + +TEST_P(InstCompressed, swsp) { + RUN_RISCV(R"( + c.swsp t0, 24(x2) + )"); +} + +INSTANTIATE_TEST_SUITE_P(RISCV, InstCompressed, + ::testing::Values(std::make_tuple(EMULATION, + YAML::Load("{}"))), + paramToString); + +} // namespace From 29f931eb6c9d3e91e509aac153e5bcaf4dcbd868 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 19 Dec 2023 16:51:01 +0000 Subject: [PATCH 037/115] Add c.ebreak and test framework --- src/lib/arch/riscv/InstructionMetadata.cc | 5 + .../riscv/instructions/compressed.cc | 341 +++++++++++++++++- 2 files changed, 344 insertions(+), 2 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 1f6ae082ea..c40933ce37 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -866,6 +866,11 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { operandCount = 3; + break; + case Opcode::RISCV_C_EBREAK: + + opcode = Opcode::RISCV_EBREAK; + break; default: break; diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index c35e064ba5..6d152f96cb 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -4,15 +4,352 @@ namespace { using InstCompressed = RISCVRegressionTest; +TEST_P(InstCompressed, lwsp) { + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0xDEADBEEF; + heap[1] = 0x12345678; + heap[2] = 0xFEEBDAED; + heap[3] = 0x87654321; + + RUN_RISCV(R"( + li a7, 214 + ecall + + li x2, 0 + add x2, x2, a0 + c.lwsp t6, 0(x2) + c.lwsp t4, 4(x2) + )"); + EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); + EXPECT_EQ(getGeneralRegister(29), 0x0000000012345678); +} + +TEST_P(InstCompressed, ldsp) { + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0xDEADBEEF; + heap[1] = 0x12345678; + heap[2] = 0xFEEBDAED; + heap[3] = 0x87654321; + + RUN_RISCV(R"( + li a7, 214 + ecall + + li x2, 0 + add x2, x2, a0 + c.ldsp t6, 0(x2) + addi x2, x2, -4 + c.ldsp t4, 8(x2) + )"); + EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); + EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); +} + TEST_P(InstCompressed, flwsp) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + RUN_RISCV(R"( - c.fldsp fa5, 24(x2) + # Get heap address + li a7, 214 + ecall + + li x2, 0 + add x2, x2, a0 + c.fldsp ft0, 0(x2) + c.fldsp ft1, 8(x2) + c.fldsp ft2, 16(x2) + c.fldsp ft3, 24(x2) )"); + + EXPECT_EQ(getFPRegister(0), 1.0); + EXPECT_EQ(getFPRegister(1), 123.456); + EXPECT_EQ(getFPRegister(2), -0.00032); + EXPECT_EQ(getFPRegister(3), 123456); } TEST_P(InstCompressed, swsp) { RUN_RISCV(R"( - c.swsp t0, 24(x2) + li t6, 0xAA + c.swsp t6, 0(sp) + + addi t6, t6, 0xAA # 0xAA + 0xAA = 154 + slli t6, t6, 16 + addi t6, t6, 0xAA # 0x15400AA + c.swsp t6, 4(sp) + )"); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x15400AA000000AA); +} + +TEST_P(InstCompressed, sdsp) { + RUN_RISCV(R"( + li t6, 0xAA + c.sdsp t6, 0(sp) + + addi t6, t6, 0xAA # 0xAA + 0xAA = 154 + slli t6, t6, 16 + addi t6, t6, 0xAA # 0x15400AA + c.sdsp t6, 8(sp) + )"); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); +} + +TEST_P(InstCompressed, fsdsp) { + RUN_RISCV(R"( + li t6, 0xAA + fmv.d.x f8, t6 + c.fsdsp f8, 0(sp) + + addi t6, t6, 0xAA # 0xAA + 0xAA = 154 + slli t6, t6, 16 + addi t6, t6, 0xAA # 0x15400AA + fmv.d.x f8, t6 + c.fsdsp f8, 8(sp) + )"); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); +} + +TEST_P(InstCompressed, lw) { + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0xDEADBEEF; + heap[1] = 0x12345678; + heap[2] = 0xFEEBDAED; + heap[3] = 0x87654321; + + RUN_RISCV(R"( + li a7, 214 + ecall + + add x8, x8, a0 + c.lw x15, 0(x8) + c.lw x13, 4(x8) + )"); + EXPECT_EQ(getGeneralRegister(15), 0xFFFFFFFFDEADBEEF); + EXPECT_EQ(getGeneralRegister(13), 0x0000000012345678); +} + +TEST_P(InstCompressed, ld) { + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0xDEADBEEF; + heap[1] = 0x12345678; + heap[2] = 0xFEEBDAED; + heap[3] = 0x87654321; + + RUN_RISCV(R"( + li a7, 214 + ecall + + add x8, x8, a0 + c.ld x15, 0(x8) + addi x8, x8, -4 + c.ld x13, 8(x8) + )"); + EXPECT_EQ(getGeneralRegister(15), 0x12345678DEADBEEF); + EXPECT_EQ(getGeneralRegister(13), 0xFEEBDAED12345678); +} + +TEST_P(InstCompressed, fld) { + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV(R"( + # Get heap address + li a7, 214 + ecall + + c.fld f8, 0(a0) + c.fld f9, 8(a0) + c.fld f10, 16(a0) + c.fld f11, 24(a0) + )"); + + EXPECT_EQ(getFPRegister(8), 1.0); + EXPECT_EQ(getFPRegister(9), 123.456); + EXPECT_EQ(getFPRegister(10), -0.00032); + EXPECT_EQ(getFPRegister(11), 123456); +} + +TEST_P(InstCompressed, addi4spn) { + RUN_RISCV(R"( + c.addi4spn + )"); +} + + +TEST_P(InstCompressed, sw) { + RUN_RISCV(R"( + c.sw + )"); +} + + +TEST_P(InstCompressed, sd) { + RUN_RISCV(R"( + c.sd + )"); +} + + +TEST_P(InstCompressed, fsd) { + RUN_RISCV(R"( + c.fsd + )"); +} + + +TEST_P(InstCompressed, j) { + RUN_RISCV(R"( + c.j + )"); +} + +TEST_P(InstCompressed, jalr) { + RUN_RISCV(R"( + c.jalr + )"); +} + + +TEST_P(InstCompressed, beqz) { + RUN_RISCV(R"( + c.beqz + )"); +} + + +TEST_P(InstCompressed, bnez) { + RUN_RISCV(R"( + c.bnez + )"); +} + + +TEST_P(InstCompressed, li) { + RUN_RISCV(R"( + c.li + )"); +} + +TEST_P(InstCompressed, lui) { + RUN_RISCV(R"( + c.lui + )"); +} + +TEST_P(InstCompressed, addi) { + RUN_RISCV(R"( + c.addi + )"); +} + +TEST_P(InstCompressed, addiw) { + RUN_RISCV(R"( + c.addiw + )"); +} + + +TEST_P(InstCompressed, addi16sp) { + RUN_RISCV(R"( + c.addi16sp + )"); +} + + + +TEST_P(InstCompressed, slli) { + RUN_RISCV(R"( + c.slli + )"); +} + + +TEST_P(InstCompressed, srli) { + RUN_RISCV(R"( + c.srli + )"); +} + + +TEST_P(InstCompressed, srai) { + RUN_RISCV(R"( + c.srai + )"); +} + +TEST_P(InstCompressed, andi) { + RUN_RISCV(R"( + c.andi + )"); +} + +TEST_P(InstCompressed, add) { + RUN_RISCV(R"( + c.add + )"); +} + +TEST_P(InstCompressed, and) { + RUN_RISCV(R"( + c.and + )"); +} + +TEST_P(InstCompressed, or) { + RUN_RISCV(R"( + c.or + )"); +} + + +TEST_P(InstCompressed, xor) { + RUN_RISCV(R"( + c.xor + )"); +} + +TEST_P(InstCompressed, sub) { + RUN_RISCV(R"( + c.sub + )"); +} + +TEST_P(InstCompressed, addw) { + RUN_RISCV(R"( + c.addw + )"); +} + +TEST_P(InstCompressed, subw) { + RUN_RISCV(R"( + c.subw + )"); +} + +TEST_P(InstCompressed, nop) { + RUN_RISCV(R"( + c.nop + )"); +} + +TEST_P(InstCompressed, ebreak) { + RUN_RISCV(R"( + c.ebreak )"); } From f38ee7c3c799a6e8a10ca3e38d8b268a4df01dd9 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 20 Dec 2023 15:30:15 +0000 Subject: [PATCH 038/115] Add some more tests --- .../riscv/instructions/compressed.cc | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 6d152f96cb..a355ad5a3f 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -85,7 +85,8 @@ TEST_P(InstCompressed, swsp) { c.swsp t6, 4(sp) )"); EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x15400AA000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + 0x15400AA000000AA); } TEST_P(InstCompressed, sdsp) { @@ -98,8 +99,10 @@ TEST_P(InstCompressed, sdsp) { addi t6, t6, 0xAA # 0x15400AA c.sdsp t6, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + 0x00000000000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), + 0x00000000015400AA); } TEST_P(InstCompressed, fsdsp) { @@ -114,8 +117,10 @@ TEST_P(InstCompressed, fsdsp) { fmv.d.x f8, t6 c.fsdsp f8, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + 0x00000000000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), + 0x00000000015400AA); } TEST_P(InstCompressed, lw) { @@ -186,32 +191,31 @@ TEST_P(InstCompressed, fld) { TEST_P(InstCompressed, addi4spn) { RUN_RISCV(R"( - c.addi4spn + c.addi4spn x8, x2, 4 + c.addi4spn x9, x2, 12 )"); + EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer() + 4); + EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 12); } - TEST_P(InstCompressed, sw) { RUN_RISCV(R"( c.sw )"); } - TEST_P(InstCompressed, sd) { RUN_RISCV(R"( c.sd )"); } - TEST_P(InstCompressed, fsd) { RUN_RISCV(R"( c.fsd )"); } - TEST_P(InstCompressed, j) { RUN_RISCV(R"( c.j @@ -224,21 +228,18 @@ TEST_P(InstCompressed, jalr) { )"); } - TEST_P(InstCompressed, beqz) { RUN_RISCV(R"( c.beqz )"); } - TEST_P(InstCompressed, bnez) { RUN_RISCV(R"( c.bnez )"); } - TEST_P(InstCompressed, li) { RUN_RISCV(R"( c.li @@ -263,29 +264,28 @@ TEST_P(InstCompressed, addiw) { )"); } - TEST_P(InstCompressed, addi16sp) { RUN_RISCV(R"( - c.addi16sp + mv x8, sp + c.addi16sp x2, 16 + mv x9, x2 )"); + EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer()); + EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 16); } - - TEST_P(InstCompressed, slli) { RUN_RISCV(R"( c.slli )"); } - TEST_P(InstCompressed, srli) { RUN_RISCV(R"( c.srli )"); } - TEST_P(InstCompressed, srai) { RUN_RISCV(R"( c.srai @@ -316,7 +316,6 @@ TEST_P(InstCompressed, or) { )"); } - TEST_P(InstCompressed, xor) { RUN_RISCV(R"( c.xor From 7b4e3ffdcab34c481b5925bceeccd99dcbd4d363 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 20 Dec 2023 15:39:31 +0000 Subject: [PATCH 039/115] Refactor getStackPointer function name for clarity --- src/include/simeng/kernel/LinuxProcess.hh | 6 +- src/lib/kernel/Linux.cc | 15 +- src/lib/kernel/LinuxProcess.cc | 2 +- test/regression/RegressionTest.cc | 2 +- test/regression/aarch64/MicroOperation.cc | 248 ++++++++----- test/regression/aarch64/SmokeTest.cc | 6 +- .../aarch64/instructions/comparison.cc | 4 +- test/regression/aarch64/instructions/load.cc | 12 +- test/regression/aarch64/instructions/sme.cc | 24 +- test/regression/aarch64/instructions/store.cc | 327 ++++++++++++------ test/regression/aarch64/instructions/sve.cc | 70 ++-- .../riscv/instructions/compressed.cc | 25 +- test/regression/riscv/instructions/store.cc | 5 +- 13 files changed, 464 insertions(+), 282 deletions(-) diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index 2f13a7727d..3192660579 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -40,7 +40,7 @@ uint64_t alignToBoundary(uint64_t value, uint64_t boundary); * * The constructed process follows a typical layout: * - * |---------------| <- start of stack + * |---------------| <- start/top of stack * | Stack | stack grows downwards * |-v-----------v-| * | | @@ -93,7 +93,7 @@ class LinuxProcess { uint64_t getEntryPoint() const; /** Get the initial stack pointer address. */ - uint64_t getStackPointer() const; + uint64_t getInitialStackPointer() const; /** Get the path of the executable. */ std::string getPath() const; @@ -132,7 +132,7 @@ class LinuxProcess { /** The page size of the process memory. */ const uint64_t pageSize_ = 4096; - /** The address of the stack pointer. */ + /** The address of the head/bottom of the stack */ uint64_t stackPointer_; /** The process image size. */ diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index 9f0b594114..10940336f1 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -23,13 +23,14 @@ namespace kernel { void Linux::createProcess(const LinuxProcess& process) { assert(process.isValid() && "Attempted to use an invalid process"); assert(processStates_.size() == 0 && "Multiple processes not yet supported"); - processStates_.push_back({.pid = 0, // TODO: create unique PIDs - .path = process.getPath(), - .startBrk = process.getHeapStart(), - .currentBrk = process.getHeapStart(), - .initialStackPointer = process.getStackPointer(), - .mmapRegion = process.getMmapStart(), - .pageSize = process.getPageSize()}); + processStates_.push_back( + {.pid = 0, // TODO: create unique PIDs + .path = process.getPath(), + .startBrk = process.getHeapStart(), + .currentBrk = process.getHeapStart(), + .initialStackPointer = process.getInitialStackPointer(), + .mmapRegion = process.getMmapStart(), + .pageSize = process.getPageSize()}); processStates_.back().fileDescriptorTable.push_back(STDIN_FILENO); processStates_.back().fileDescriptorTable.push_back(STDOUT_FILENO); processStates_.back().fileDescriptorTable.push_back(STDERR_FILENO); diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index b61470919c..226eada99a 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -108,7 +108,7 @@ uint64_t LinuxProcess::getProcessImageSize() const { return size_; } uint64_t LinuxProcess::getEntryPoint() const { return entryPoint_; } -uint64_t LinuxProcess::getStackPointer() const { return stackPointer_; } +uint64_t LinuxProcess::getInitialStackPointer() const { return stackPointer_; } void LinuxProcess::createStack(char** processImage) { // Decrement the stack pointer and populate with initial stack state diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 66d6501818..b57fb9d47b 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -70,7 +70,7 @@ void RegressionTest::run(const char* source, const char* triple, // Populate the heap with initial data (specified by the test being run). ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), - process_->getStackPointer()); + process_->getInitialStackPointer()); std::copy(initialHeapData_.begin(), initialHeapData_.end(), processMemory_ + process_->getHeapStart()); diff --git a/test/regression/aarch64/MicroOperation.cc b/test/regression/aarch64/MicroOperation.cc index 6aa42fd87a..437fd7d01c 100644 --- a/test/regression/aarch64/MicroOperation.cc +++ b/test/regression/aarch64/MicroOperation.cc @@ -647,14 +647,22 @@ TEST_P(MicroOp, storePairD) { stp d4, d5, [sp, #16] stp d6, d7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -3.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 3.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 5.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), -1.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), -0.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 0.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 1.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + -5.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + -3.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 3.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 5.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + -1.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + -0.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + 0.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + 1.5); } TEST_P(MicroOp, storePairQ) { @@ -694,37 +702,37 @@ TEST_P(MicroOp, storePairQ) { stp q4, q5, [sp, #32] stp q6, q7, [sp, #-32]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), 0xCAFEABBACAFEABBA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), 0xFEDCBAFEDCBAFEDC); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 960), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 960), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 952), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 952), 0xFEDCBAFEDCBAFEDC); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 944), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 944), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 936), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 936), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 928), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 928), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 920), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 920), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 912), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 912), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 904), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 904), 0xCAFEABBACAFEABBA); } @@ -746,14 +754,22 @@ TEST_P(MicroOp, storePairS) { stp s4, s5, [sp, #8] stp s6, s7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), -3.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 5.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), -0.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 0.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 1.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + -5.0f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + -3.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 3.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + 5.0f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + -1.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1004), + -0.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 0.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 996), + 1.5f); } TEST_P(MicroOp, storePairW) { @@ -774,14 +790,22 @@ TEST_P(MicroOp, storePairW) { stp w4, w5, [sp, #8] stp w6, w7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 72); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 84); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + 96); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1004), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 60); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 996), + 72); } TEST_P(MicroOp, storePairX) { @@ -802,14 +826,22 @@ TEST_P(MicroOp, storePairX) { stp x4, x5, [sp, #16] stp x6, x7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 84); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 96); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + 60); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + 72); } TEST_P(MicroOp, storeB) { @@ -837,10 +869,14 @@ TEST_P(MicroOp, storeB) { str b2, [sp, #1] str b3, [sp, #-1]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1023), 0xFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), 0xBA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1021), 0xCA); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 0xAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1023), + 0xFE); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1022), + 0xBA); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1021), + 0xCA); } TEST_P(MicroOp, storeD) { @@ -857,10 +893,14 @@ TEST_P(MicroOp, storeD) { str d2, [sp, #8] str d3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 1.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + -3.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 3.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + -1.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 1.5); } TEST_P(MicroOp, storeH) { @@ -888,13 +928,13 @@ TEST_P(MicroOp, storeH) { str h2, [sp, #2] str h3, [sp, #-2]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), 0xABBA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1022), 0x5678); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), 0xCAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1018), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1018), 0x1234); } @@ -927,21 +967,21 @@ TEST_P(MicroOp, storeQ) { str q2, [sp, #16] str q3, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), 0xCAFEABBACAFEABBA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), 0xFEDCBAFEDCBAFEDC); } @@ -959,10 +999,14 @@ TEST_P(MicroOp, storeS) { str s2, [sp, #4] str s3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 3.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -1.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 1.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + -3.0f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + 3.0f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + -1.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + 1.5f); } TEST_P(MicroOp, storeW) { @@ -979,10 +1023,14 @@ TEST_P(MicroOp, storeW) { str w2, [sp, #4] str w3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + 36); } TEST_P(MicroOp, storeX) { @@ -999,10 +1047,14 @@ TEST_P(MicroOp, storeX) { str x2, [sp, #8] str x3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 36); } TEST_P(MicroOp, storeThenLoad) { @@ -1026,10 +1078,14 @@ TEST_P(MicroOp, storeThenLoad) { ldr x7, [sp, #8] ldr x8, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 36); EXPECT_EQ(getGeneralRegister(5), 12); EXPECT_EQ(getGeneralRegister(6), 24); EXPECT_EQ(getGeneralRegister(7), 36); @@ -1061,14 +1117,22 @@ TEST_P(MicroOp, storeThenLoadPair) { ldp x12, x13, [sp, #16] ldp x14, x15, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 24); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 84); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 96); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + 36); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + 48); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + 60); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + 72); EXPECT_EQ(getGeneralRegister(8), 12); EXPECT_EQ(getGeneralRegister(9), 24); EXPECT_EQ(getGeneralRegister(10), 36); diff --git a/test/regression/aarch64/SmokeTest.cc b/test/regression/aarch64/SmokeTest.cc index fad544d04c..f1b3ecfd24 100644 --- a/test/regression/aarch64/SmokeTest.cc +++ b/test/regression/aarch64/SmokeTest.cc @@ -34,8 +34,10 @@ TEST_P(SmokeTest, stack) { str w0, [sp, -4] str w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 7u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 42u); } // Test that we can store values to the heap diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 3aed7d44eb..06b23bc73f 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -36,7 +36,7 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(0)), 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 100); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 89); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 89); // 64-bit initialHeapData_.resize(16); @@ -68,7 +68,7 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(0)), 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 101); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 76); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 76); } // Test that NZCV flags are set correctly by the 32-bit cmn instruction diff --git a/test/regression/aarch64/instructions/load.cc b/test/regression/aarch64/instructions/load.cc index 8f0419d825..0a483d1cdc 100644 --- a/test/regression/aarch64/instructions/load.cc +++ b/test/regression/aarch64/instructions/load.cc @@ -605,10 +605,14 @@ TEST_P(InstLoad, ldadd) { EXPECT_EQ(getGeneralRegister(6), 48); EXPECT_EQ(getGeneralRegister(7), 128); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 112); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 64); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 960), 176); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 928), 128); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 112); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + 64); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 960), + 176); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 928), + 128); } TEST_P(InstLoad, ldar) { diff --git a/test/regression/aarch64/instructions/sme.cc b/test/regression/aarch64/instructions/sme.cc index 847b1cb604..af209949b2 100644 --- a/test/regression/aarch64/instructions/sme.cc +++ b/test/regression/aarch64/instructions/sme.cc @@ -300,9 +300,9 @@ TEST_P(InstSme, st1d) { st1d {za1h.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), - src[i % 2]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 8)), + src[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src[i % 2]); } @@ -361,9 +361,9 @@ TEST_P(InstSme, st1d) { st1d {za1v.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), - src_vert[i % 2]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 8)), + src_vert[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src_vert[i % 2]); } @@ -424,9 +424,9 @@ TEST_P(InstSme, st1w) { st1w {za1h.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), - src[i % 4]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 4)), + src[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src[i % 4]); } @@ -485,9 +485,9 @@ TEST_P(InstSme, st1w) { st1w {za1v.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), - src_vert[i % 4]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 4)), + src_vert[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src_vert[i % 4]); } diff --git a/test/regression/aarch64/instructions/store.cc b/test/regression/aarch64/instructions/store.cc index 2ccd8feec0..f5dd4adcdf 100644 --- a/test/regression/aarch64/instructions/store.cc +++ b/test/regression/aarch64/instructions/store.cc @@ -21,10 +21,14 @@ TEST_P(InstStore, stlr) { stlrb w3, [sp] add sp, sp, #1 )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 0xAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 3), + 0x12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + 0xCD); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1), + 0x34); // stlr RUN_AARCH64(R"( @@ -46,12 +50,14 @@ TEST_P(InstStore, stlr) { add sp, sp, #4 )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), 0xFFFFFFFFFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0xBEEF); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 0xBEEF); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), 0xFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xBABA); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 0xBABA); } TEST_P(InstStore, strb) { @@ -70,12 +76,17 @@ TEST_P(InstStore, strb) { mov x6, -16 strb w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 18), 0x12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 0xAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 3), + 0x12); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + 0xCD); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1), + 0x34); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0xAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 18), + 0x12); } TEST_P(InstStore, strh) { @@ -94,12 +105,18 @@ TEST_P(InstStore, strh) { mov x6, -16 strh w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 6), 0x1234); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xCD89); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0x3401); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 0x1234); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 0xABAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 6), + 0x1234); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 0xCD89); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + 0x3401); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + 0xABAB); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + 0x1234); } TEST_P(InstStore, strd) { @@ -119,12 +136,18 @@ TEST_P(InstStore, strd) { mov x6, -16 str d1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + 2.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + 7.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 16.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 2.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + -0.125); } TEST_P(InstStore, strq) { @@ -135,11 +158,16 @@ TEST_P(InstStore, strq) { str q0, [sp], -32 str q1, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0.25); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 0.25); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + 0.25); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + 0.25); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 32); } TEST_P(InstStore, strs) { @@ -159,12 +187,17 @@ TEST_P(InstStore, strs) { mov x6, -8 str s1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 28), + -0.125f); } TEST_P(InstStore, strw) { @@ -183,17 +216,17 @@ TEST_P(InstStore, strw) { mov x6, -16 str w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), 0xABABull << 16); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), 0x1234ull << 16); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), 0xCD89ull << 16); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), 0x3401ull << 16); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0xABABull << 16); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), 0x1234ull << 16); } @@ -214,17 +247,17 @@ TEST_P(InstStore, strx) { mov x6, -16 str x1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), 0xABABull << 32); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), 0x1234ull << 32); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), 0xCD89ull << 32); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), 0x3401ull << 32); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0xABABull << 32); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), 0x1234ull << 32); } @@ -253,7 +286,8 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #15 st1 {v0.b}[12], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), static_cast(1)); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -287,7 +321,8 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #14 st1 {v0.h}[7], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0xab); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -319,7 +354,8 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #12 st1 {v0.s}[3], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0.5f); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 1); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 2); @@ -344,7 +380,8 @@ TEST_P(InstStore, st1_single_struct) { st1 {v0.d}[1], [sp], x4 st1 {v1.d}[0], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 0.5); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 1000UL); @@ -362,7 +399,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b}, [sp], x0 st1 {v0.16b, v1.16b}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 16; i++) { @@ -385,7 +423,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d}, [sp], x0 st1 {v0.2d, v1.2d}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 2; i++) { @@ -408,7 +447,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s}, [sp], x0 st1 {v0.4s, v1.4s}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 4; i++) { @@ -433,7 +473,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [sp], x0 st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 16; i++) { @@ -466,7 +507,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [sp], x0 st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 2; i++) { @@ -499,7 +541,8 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [sp], x0 st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 4; i++) { @@ -543,9 +586,12 @@ TEST_P(InstStore, st1fourv_post) { st1 {v4.2s, v5.2s, v6.2s, v7.2s}, [x1], x2 )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); - EXPECT_EQ(getGeneralRegister(0), process_->getStackPointer() - 32); - EXPECT_EQ(getGeneralRegister(1), process_->getStackPointer() - 15); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(0), + process_->getInitialStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(1), + process_->getInitialStackPointer() - 15); for (int i = 0; i < 2; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -595,9 +641,11 @@ TEST_P(InstStore, st1fourv_post) { st1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x1], x2 )"); EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 128); - EXPECT_EQ(getGeneralRegister(0), process_->getStackPointer() - 64); - EXPECT_EQ(getGeneralRegister(1), process_->getStackPointer() - 47); + process_->getInitialStackPointer() - 128); + EXPECT_EQ(getGeneralRegister(0), + process_->getInitialStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(1), + process_->getInitialStackPointer() - 47); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -638,7 +686,8 @@ TEST_P(InstStore, st2_multi_struct) { st2 {v2.4s, v3.4s}, [sp], x1 st2 {v0.4s, v1.4s}, [sp], #32 )"); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer()); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer()); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) - 32 + 8 * i), @@ -670,14 +719,22 @@ TEST_P(InstStore, stpd) { stp d3, d0, [sp, 16] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 64), + 2.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), + -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + 7.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + 7.5); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + 16.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 16.0); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 2.0); } TEST_P(InstStore, stps) { @@ -692,14 +749,21 @@ TEST_P(InstStore, stps) { stp s2, s3, [sp, 8]! stp s3, s0, [sp, 8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 28), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), 2.f); } TEST_P(InstStore, stpwi) { @@ -708,8 +772,10 @@ TEST_P(InstStore, stpwi) { movz w1, #42 stp w0, w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 7u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 42u); } TEST_P(InstStore, stpq) { @@ -724,23 +790,40 @@ TEST_P(InstStore, stpq) { stp q2, q3, [sp, 32]! stp q3, q0, [sp, 32] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 128), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 120), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 112), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 104), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 96), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 88), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 80), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 72), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.f); - EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 128), + 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 120), + 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 112), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 104), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 96), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 88), + -0.125f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 80), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 72), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 64), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + 7.5f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + 16.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + 2.f); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 2.f); + EXPECT_EQ(getGeneralRegister(31), + process_->getInitialStackPointer() - 64); } TEST_P(InstStore, stpx) { @@ -758,12 +841,18 @@ TEST_P(InstStore, stpx) { stp x2, x3, [sp] stp x4, x5, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 42u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 8u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 43u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 9u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 44u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + 7u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + 8u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + 43u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + 9u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + 44u); } TEST_P(InstStore, stur) { @@ -771,32 +860,38 @@ TEST_P(InstStore, stur) { movz w0, #42 stur w0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 42u); RUN_AARCH64(R"( movz x0, #42 stur x0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + 42u); RUN_AARCH64(R"( fmov s0, -0.125 stur s0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + -0.125); RUN_AARCH64(R"( fmov d0, -0.125 stur d0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + -0.125); RUN_AARCH64(R"( fmov v0.2d, -0.125 stur q0, [sp, #-16] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + -0.125); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + -0.125); } TEST_P(InstStore, sturh) { @@ -806,8 +901,10 @@ TEST_P(InstStore, sturh) { movz w1, #128 sturh w1, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 42u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 128u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + 42u); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + 128u); } INSTANTIATE_TEST_SUITE_P(AArch64, InstStore, diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index 4334439695..abba705be4 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -6196,13 +6196,14 @@ TEST_P(InstSve, st1b) { )"); for (int i = 0; i < (VL / 8); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + i), - src[i % 16]); + EXPECT_EQ( + getMemoryValue(process_->getInitialStackPointer() - 4095 + i), + src[i % 16]); } for (int i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(4 * (VL / 16) + i), src[i % 16]); } - uint64_t base = process_->getStackPointer() - 8190 + 4 * (VL / 8); + uint64_t base = process_->getInitialStackPointer() - 8190 + 4 * (VL / 8); for (int i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(base + i), src[i % 16]); } @@ -6241,8 +6242,9 @@ TEST_P(InstSve, st1b_scatter) { )"); for (uint64_t i = 0; i < VL / 64; i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - (3 * i)), - src[(8 * i) % 16]); + EXPECT_EQ( + getMemoryValue(process_->getInitialStackPointer() - (3 * i)), + src[(8 * i) % 16]); } for (uint64_t i = 0; i < VL / 128; i++) { @@ -6360,9 +6362,9 @@ TEST_P(InstSve, st1d) { )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), - src[i % 4]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 8)), + src[i % 4]); } for (int i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(65792 + (i * 8)), src[i % 4]); @@ -6400,11 +6402,11 @@ TEST_P(InstSve, st2d) { )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + - (2 * i * 8)), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (2 * i * 8)), 3); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + - (2 * i * 8) + 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (2 * i * 8) + 8), 4); } @@ -6505,9 +6507,9 @@ TEST_P(InstSve, st1w) { )"); for (int i = 0; i < (VL / 32); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), - src[i % 4]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 4)), + src[i % 4]); } for (int i = 0; i < (VL / 32); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (i * 4)), src[i % 4]); @@ -6580,22 +6582,27 @@ TEST_P(InstSve, st1w) { // 0x1234567812345678u, 0x9876543298765432u, // 0xABCDEF01ABCDEF01u}); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), // 0xDEADBEEF); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() // + 4), // 0x12345678); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), // 0x98765432); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 12), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + + // 12), // 0xABCDEF01); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 16), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + + // 16), // 0xDEADBEEF); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 20), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + + // 20), // 0x12345678); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 24), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + + // 24), // 0x98765432); - // EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 28), + // EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + + // 28), // 0xABCDEF01); // EXPECT_EQ(getMemoryValue(64 + (3 * 4)), 0xDEADBEEF); @@ -6625,8 +6632,9 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #0, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + i), - 0xFF); + EXPECT_EQ( + getMemoryValue(process_->getInitialStackPointer() - 4095 + i), + 0xFF); } fillHeap(heap8, {0xDE}, VL / 64); @@ -6642,7 +6650,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #1, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64)) + i), 0xDE); } @@ -6660,7 +6668,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #2, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64) * 2) + i), 0x12); } @@ -6678,7 +6686,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #3, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64) * 3) + i), 0x98); } @@ -6707,9 +6715,9 @@ TEST_P(InstSve, str_vector) { str z1, [x1, #4, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ( - getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), - src[i % 8]); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + 4095 + (i * 8)), + src[i % 8]); } for (int i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (VL / 2) + (i * 8)), diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index a355ad5a3f..b859effc97 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -84,8 +84,9 @@ TEST_P(InstCompressed, swsp) { addi t6, t6, 0xAA # 0x15400AA c.swsp t6, 4(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + 0x000000AA); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x15400AA000000AA); } @@ -99,9 +100,9 @@ TEST_P(InstCompressed, sdsp) { addi t6, t6, 0xAA # 0x15400AA c.sdsp t6, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); } @@ -117,9 +118,9 @@ TEST_P(InstCompressed, fsdsp) { fmv.d.x f8, t6 c.fsdsp f8, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); } @@ -194,8 +195,10 @@ TEST_P(InstCompressed, addi4spn) { c.addi4spn x8, x2, 4 c.addi4spn x9, x2, 12 )"); - EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer() + 4); - EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 12); + EXPECT_EQ(getGeneralRegister(8), + process_->getInitialStackPointer() + 4); + EXPECT_EQ(getGeneralRegister(9), + process_->getInitialStackPointer() + 12); } TEST_P(InstCompressed, sw) { @@ -270,8 +273,10 @@ TEST_P(InstCompressed, addi16sp) { c.addi16sp x2, 16 mv x9, x2 )"); - EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer()); - EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 16); + EXPECT_EQ(getGeneralRegister(8), + process_->getInitialStackPointer()); + EXPECT_EQ(getGeneralRegister(9), + process_->getInitialStackPointer() + 16); } TEST_P(InstCompressed, slli) { diff --git a/test/regression/riscv/instructions/store.cc b/test/regression/riscv/instructions/store.cc index d03f7c4585..562e85008d 100644 --- a/test/regression/riscv/instructions/store.cc +++ b/test/regression/riscv/instructions/store.cc @@ -78,7 +78,8 @@ TEST_P(InstStore, sw) { EXPECT_EQ(getGeneralRegister(10), 64); EXPECT_EQ(getMemoryValue(64), 0xAAADBE000000AA78); EXPECT_EQ(getMemoryValue(69), 0x0087015400AAADBE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x5400AA00); + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + 0x5400AA00); } TEST_P(InstStore, sd) { @@ -107,7 +108,7 @@ TEST_P(InstStore, sd) { EXPECT_EQ(getGeneralRegister(10), 68); EXPECT_EQ(getMemoryValue(64), 0x0154000000AA5678); EXPECT_EQ(getMemoryValue(68), 0x8765000001540000); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 4), + EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 4), 0x000154000000AA01); } From 221227eecbbd06a46e4585b819a4bcb094ac136a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 21 Dec 2023 13:00:48 +0000 Subject: [PATCH 040/115] Add runCompressed for finer control of extensions used in tests --- test/regression/riscv/RISCVRegressionTest.cc | 10 ++ test/regression/riscv/RISCVRegressionTest.hh | 19 ++ .../riscv/instructions/compressed.cc | 169 +++++++++++++----- 3 files changed, 157 insertions(+), 41 deletions(-) diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index 8216667746..9e12925001 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -11,8 +11,18 @@ void RISCVRegressionTest::run(const char* source) { LLVMInitializeRISCVTargetMC(); LLVMInitializeRISCVAsmParser(); + RegressionTest::run(source, "riscv64", "+m,+a,+f,+d"); +} + +void RISCVRegressionTest::runCompressed(const char* source) { + // Initialise LLVM + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTargetMC(); + LLVMInitializeRISCVAsmParser(); + RegressionTest::run(source, "riscv64", "+m,+a,+f,+d,+c"); } + // TODO create yaml YAML::Node RISCVRegressionTest::generateConfig() const { YAML::Node config = YAML::Load(RISCV_CONFIG); diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 514f86f84f..e5251b3182 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -60,6 +60,21 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return +/** A helper macro to run a snippet of RISCV 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 above 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"; \ + runCompressed(sourceWithTerminator.c_str()); \ + } \ + if (HasFatalFailure()) return + /** The test fixture for all RISCV regression tests. */ class RISCVRegressionTest : public RegressionTest { protected: @@ -68,6 +83,10 @@ class RISCVRegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source); + /** Run the assembly code in `source` with compressed extension in the target + * ISA. */ + void runCompressed(const char* source); + /** Generate a default YAML-formatted configuration. */ YAML::Node generateConfig() const override; diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index b859effc97..84d6f8feb6 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -12,7 +12,7 @@ TEST_P(InstCompressed, lwsp) { heap[2] = 0xFEEBDAED; heap[3] = 0x87654321; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li a7, 214 ecall @@ -33,7 +33,7 @@ TEST_P(InstCompressed, ldsp) { heap[2] = 0xFEEBDAED; heap[3] = 0x87654321; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li a7, 214 ecall @@ -55,7 +55,7 @@ TEST_P(InstCompressed, flwsp) { heap[2] = -0.00032; heap[3] = 123456; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( # Get heap address li a7, 214 ecall @@ -75,7 +75,7 @@ TEST_P(InstCompressed, flwsp) { } TEST_P(InstCompressed, swsp) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li t6, 0xAA c.swsp t6, 0(sp) @@ -91,7 +91,7 @@ TEST_P(InstCompressed, swsp) { } TEST_P(InstCompressed, sdsp) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li t6, 0xAA c.sdsp t6, 0(sp) @@ -107,7 +107,7 @@ TEST_P(InstCompressed, sdsp) { } TEST_P(InstCompressed, fsdsp) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li t6, 0xAA fmv.d.x f8, t6 c.fsdsp f8, 0(sp) @@ -132,7 +132,7 @@ TEST_P(InstCompressed, lw) { heap[2] = 0xFEEBDAED; heap[3] = 0x87654321; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li a7, 214 ecall @@ -152,7 +152,7 @@ TEST_P(InstCompressed, ld) { heap[2] = 0xFEEBDAED; heap[3] = 0x87654321; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( li a7, 214 ecall @@ -173,7 +173,7 @@ TEST_P(InstCompressed, fld) { heap[2] = -0.00032; heap[3] = 123456; - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( # Get heap address li a7, 214 ecall @@ -191,7 +191,7 @@ TEST_P(InstCompressed, fld) { } TEST_P(InstCompressed, addi4spn) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.addi4spn x8, x2, 4 c.addi4spn x9, x2, 12 )"); @@ -202,73 +202,160 @@ TEST_P(InstCompressed, addi4spn) { } TEST_P(InstCompressed, sw) { - RUN_RISCV(R"( - c.sw + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0x12345678; + heap[1] = 0xDEADBEEF; + heap[2] = 0x87654321; + + RUN_RISCV_COMP(R"( + # Get heap address + li a7, 214 + ecall + + li x8, 0xAA + c.sw x8, 0(a0) + + addi x8, x8, 0xAA # 0xAA + 0xAA = 154 + slli x8, x8, 16 + addi x8, x8, 0xAA # 0x15400AA + c.sw x8, 4(a0) )"); + + EXPECT_EQ(getGeneralRegister(10), 32); + EXPECT_EQ(getMemoryValue(32), 0x015400AA000000AA); + EXPECT_EQ(getMemoryValue(36), 0x87654321015400AA); } TEST_P(InstCompressed, sd) { - RUN_RISCV(R"( - c.sd + initialHeapData_.resize(16); + uint32_t* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 0x12345678; + heap[1] = 0xDEADBEEF; + heap[2] = 0x87654321; + + RUN_RISCV_COMP(R"( + # Get heap address + li a7, 214 + ecall + + li x8, 0xAA + c.sd x8, 0(a0) + + addi x8, x8, 0xAA # 0xAA + 0xAA = 154 + slli x8, x8, 16 + addi x8, x8, 0xAA # 0x15400AA + c.sd x8, 8(a0) )"); + + EXPECT_EQ(getGeneralRegister(10), 32); + EXPECT_EQ(getMemoryValue(32), 0x00000000000000AA); + EXPECT_EQ(getMemoryValue(40), 0x00000000015400AA); } TEST_P(InstCompressed, fsd) { - RUN_RISCV(R"( - c.fsd - )"); + initialHeapData_.resize(32); + double* heap = reinterpret_cast(initialHeapData_.data()); + heap[0] = 1.0; + heap[1] = 123.456; + heap[2] = -0.00032; + heap[3] = 123456; + + RUN_RISCV_COMP(R"( + # Get heap address + li a7, 214 + ecall + + fld fa0, 0(a0) + fld fa1, 8(a0) + fld fa2, 16(a0) + fld fa3, 24(a0) + + c.fsd fa3, 0(a0) + c.fsd fa2, 8(a0) + c.fsd fa1, 16(a0) + c.fsd fa0, 24(a0) + )"); + + EXPECT_EQ(getFPRegister(10), 1.0); + EXPECT_EQ(getFPRegister(11), 123.456); + EXPECT_EQ(getFPRegister(12), -0.00032); + EXPECT_EQ(getFPRegister(13), 123456); + + EXPECT_EQ(getGeneralRegister(10), 32); + + EXPECT_EQ(getMemoryValue(32), 123456); + EXPECT_EQ(getMemoryValue(40), -0.00032); + EXPECT_EQ(getMemoryValue(48), 123.456); + EXPECT_EQ(getMemoryValue(56), 1.0); } TEST_P(InstCompressed, j) { - RUN_RISCV(R"( - c.j - )"); + // Labels needed as LLVM eagerly uses compressed instructions e.g. addi -> + // c.addi causing manual jump offsets to be confusing + RUN_RISCV_COMP(R"( + c.j jump #c.j 0xc + jumpa: + addi t6, t6, 10 + jal t1, jumpc #jal t1, 0xc + jump: + addi t5, t5, 5 + jal jumpa #jal -0xc + jumpc: + addi t4, t4, 3 + )"); + EXPECT_EQ(getGeneralRegister(30), 5); + EXPECT_EQ(getGeneralRegister(31), 10); + EXPECT_EQ(getGeneralRegister(29), 3); + EXPECT_EQ(getGeneralRegister(6), 8); + EXPECT_EQ(getGeneralRegister(1), 14); + EXPECT_EQ(getGeneralRegister(0), 0); } TEST_P(InstCompressed, jalr) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.jalr )"); } TEST_P(InstCompressed, beqz) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.beqz )"); } TEST_P(InstCompressed, bnez) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.bnez )"); } TEST_P(InstCompressed, li) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.li )"); } TEST_P(InstCompressed, lui) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.lui )"); } TEST_P(InstCompressed, addi) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.addi )"); } TEST_P(InstCompressed, addiw) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.addiw )"); } TEST_P(InstCompressed, addi16sp) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( mv x8, sp c.addi16sp x2, 16 mv x9, x2 @@ -280,79 +367,79 @@ TEST_P(InstCompressed, addi16sp) { } TEST_P(InstCompressed, slli) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.slli )"); } TEST_P(InstCompressed, srli) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.srli )"); } TEST_P(InstCompressed, srai) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.srai )"); } TEST_P(InstCompressed, andi) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.andi )"); } TEST_P(InstCompressed, add) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.add )"); } TEST_P(InstCompressed, and) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.and )"); } TEST_P(InstCompressed, or) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.or )"); } TEST_P(InstCompressed, xor) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.xor )"); } TEST_P(InstCompressed, sub) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.sub )"); } TEST_P(InstCompressed, addw) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.addw )"); } TEST_P(InstCompressed, subw) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.subw )"); } TEST_P(InstCompressed, nop) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.nop )"); } TEST_P(InstCompressed, ebreak) { - RUN_RISCV(R"( + RUN_RISCV_COMP(R"( c.ebreak )"); } From 2f91d104028fbda26d7176e08af20f5ff4f33d52 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 21 Dec 2023 16:41:00 +0000 Subject: [PATCH 041/115] Complete C extension tests --- test/regression/riscv/CMakeLists.txt | 2 + .../riscv/instructions/compressed.cc | 256 ++++++++++++++++-- 2 files changed, 239 insertions(+), 19 deletions(-) diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index 4b39e35575..1636b78369 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -18,6 +18,8 @@ add_executable(regression-riscv target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(regression-riscv regression-test-base) +target_link_libraries(regression-riscv gmock_main) + # Define a macro so that tests can find data files target_compile_definitions(regression-riscv PRIVATE diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 84d6f8feb6..c466e82796 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -1,4 +1,7 @@ #include "RISCVRegressionTest.hh" +#include "gmock/gmock.h" + +using ::testing::HasSubstr; namespace { @@ -314,44 +317,113 @@ TEST_P(InstCompressed, j) { TEST_P(InstCompressed, jalr) { RUN_RISCV_COMP(R"( - c.jalr + li x8, 12 + c.jalr x8 + mv t0, ra + addi t6, t6, 10 + li x8, 20 + c.jalr x8 + mv t1, ra + addi t5, t5, 5 + li x8, 4 + c.jalr x8 + mv t2, ra + addi t4, t4, 3 )"); + EXPECT_EQ(getGeneralRegister(30), 5); + EXPECT_EQ(getGeneralRegister(31), 10); + EXPECT_EQ(getGeneralRegister(29), 3); + EXPECT_EQ(getGeneralRegister(5), 20); + EXPECT_EQ(getGeneralRegister(6), 4); + EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_EQ(getGeneralRegister(1), 12); } TEST_P(InstCompressed, beqz) { RUN_RISCV_COMP(R"( - c.beqz - )"); + addi x8, x8, 2 + c.beqz x8, b1 + addi x10, x10, 10 + li x9, 0 + c.beqz x9, b2 + j b3 + b1: + addi x10, x10, 5 + b2: + addi x11, x11, 10 + j b4 + b3: + addi x11, x11, 5 + b4: + )"); + EXPECT_EQ(getGeneralRegister(10), 10); + EXPECT_EQ(getGeneralRegister(11), 10); } TEST_P(InstCompressed, bnez) { RUN_RISCV_COMP(R"( - c.bnez + addi x8, x8, 0 + c.bnez x8, b1 + addi x10, x10, 10 + li x9, 2 + c.bnez x9, b2 + j b3 + b1: + addi x10, x10, 5 + b2: + addi x11, x11, 10 + j b4 + b3: + addi x11, x11, 5 + b4: )"); } TEST_P(InstCompressed, li) { RUN_RISCV_COMP(R"( - c.li + addi a5, a5, 12 + c.li a5, 0 + addi a4, a4, 12 + c.li a4, -32 + addi a3, a3, 12 + c.li a3, 31 )"); + EXPECT_EQ(getGeneralRegister(15), 0); + EXPECT_EQ(getGeneralRegister(14), -32); + EXPECT_EQ(getGeneralRegister(13), 31); } TEST_P(InstCompressed, lui) { RUN_RISCV_COMP(R"( - c.lui + c.lui t3, 4 + c.lui t4, 0xFFFFC )"); + EXPECT_EQ(getGeneralRegister(28), 4 << 12); + EXPECT_EQ(getGeneralRegister(29), -4ull << 12); } TEST_P(InstCompressed, addi) { RUN_RISCV_COMP(R"( - c.addi + c.addi t3, 3 + c.addi t4, 6 + c.addi t3, 30 + c.addi zero, 16 )"); + EXPECT_EQ(getGeneralRegister(29), 6u); + EXPECT_EQ(getGeneralRegister(28), 33u); + EXPECT_EQ(getGeneralRegister(0), 0); } TEST_P(InstCompressed, addiw) { RUN_RISCV_COMP(R"( - c.addiw + addi t3, t3, 91 + slli t3, t3, 28 + addiw t5, t3, -5 + addiw t6, t2, -5 )"); + EXPECT_EQ(getGeneralRegister(28), 24427626496); + EXPECT_EQ(getGeneralRegister(30), -1342177285); + EXPECT_EQ(getGeneralRegister(31), -5); } TEST_P(InstCompressed, addi16sp) { @@ -368,80 +440,226 @@ TEST_P(InstCompressed, addi16sp) { TEST_P(InstCompressed, slli) { RUN_RISCV_COMP(R"( - c.slli + addi t4, t4, 6 + c.slli t4, 5 )"); + EXPECT_EQ(getGeneralRegister(29), 192); } TEST_P(InstCompressed, srli) { RUN_RISCV_COMP(R"( - c.srli + addi x8, x8, -4 + c.srli x8, 61 )"); + EXPECT_EQ(getGeneralRegister(8), 7); } TEST_P(InstCompressed, srai) { RUN_RISCV_COMP(R"( - c.srai + addi x8, x8, -4 + add t0, t0, x8 + c.srai x8, 1 + addi x9, t0, 8 + c.srai x9, 1 )"); + EXPECT_EQ(getGeneralRegister(8), -2); + EXPECT_EQ(getGeneralRegister(9), 2); } TEST_P(InstCompressed, andi) { RUN_RISCV_COMP(R"( - c.andi + addi x9, x9, 3 + addi t4, t4, 5 + and x8, x9, t4 + c.andi x8, 9 + c.andi x9, -7 )"); + EXPECT_EQ(getGeneralRegister(8), 0b0001); + EXPECT_EQ(getGeneralRegister(9), 1); } TEST_P(InstCompressed, add) { RUN_RISCV_COMP(R"( - c.add + addi x8, x8, 3 + addi x9, x9, 6 + c.add x8, x9 )"); + EXPECT_EQ(getGeneralRegister(8), 9u); + EXPECT_EQ(getGeneralRegister(9), 6u); } TEST_P(InstCompressed, and) { RUN_RISCV_COMP(R"( - c.and + addi x8, x8, 3 + addi x9, x9, 5 + c.and x8, x9 )"); + EXPECT_EQ(getGeneralRegister(8), 0b0001); } TEST_P(InstCompressed, or) { RUN_RISCV_COMP(R"( - c.or + addi x8, x8, 3 + addi x9, x9, 5 + c.or x8, x9 )"); + EXPECT_EQ(getGeneralRegister(8), 0b0111); } TEST_P(InstCompressed, xor) { RUN_RISCV_COMP(R"( - c.xor + addi x8, x8, 3 + addi x9, x9, 5 + c.xor x8, x9 )"); + EXPECT_EQ(getGeneralRegister(8), 0b0110); } TEST_P(InstCompressed, sub) { RUN_RISCV_COMP(R"( - c.sub + addi x8, x8, 3 + addi x9, x9, 6 + mv x10, x8 + c.sub x8, x9 + c.sub x9, x10 )"); + EXPECT_EQ(getGeneralRegister(8), -3); + EXPECT_EQ(getGeneralRegister(9), 3); } TEST_P(InstCompressed, addw) { RUN_RISCV_COMP(R"( - c.addw + addi x9, x9, -7 + addi x8, x8, 3 + mv x11, x8 + addi x10, x10, 6 + c.addw x8, x10 + c.addw x9, x11 )"); + EXPECT_EQ(getGeneralRegister(8), 9u); + EXPECT_EQ(getGeneralRegister(9), -4); } TEST_P(InstCompressed, subw) { RUN_RISCV_COMP(R"( - c.subw + addi x9, x9, 3 + addi x10, x10, 6 + mv x11, x10 + mv x12, x9 + c.subw x9, x10 + c.subw x10, x12 + + li x12, -1 + addi x11, x11, -8 + c.subw x12, x11 )"); + EXPECT_EQ(getGeneralRegister(9), -3); + EXPECT_EQ(getGeneralRegister(10), 3); + + EXPECT_EQ(getGeneralRegister(11), -2); + EXPECT_EQ(getGeneralRegister(12), 0x0000000000000001); } TEST_P(InstCompressed, nop) { RUN_RISCV_COMP(R"( + li x8, 1234 + )"); + EXPECT_EQ(getGeneralRegister(0), 0); + EXPECT_EQ(getGeneralRegister(1), 0); + EXPECT_EQ(getGeneralRegister(2), 199840); + EXPECT_EQ(getGeneralRegister(3), 0); + EXPECT_EQ(getGeneralRegister(4), 0); + EXPECT_EQ(getGeneralRegister(5), 0); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(8), 1234); + EXPECT_EQ(getGeneralRegister(9), 0); + EXPECT_EQ(getGeneralRegister(10), 0); + EXPECT_EQ(getGeneralRegister(11), 0); + EXPECT_EQ(getGeneralRegister(12), 0); + EXPECT_EQ(getGeneralRegister(13), 0); + EXPECT_EQ(getGeneralRegister(14), 0); + EXPECT_EQ(getGeneralRegister(15), 0); + EXPECT_EQ(getGeneralRegister(16), 0); + EXPECT_EQ(getGeneralRegister(17), 0); + EXPECT_EQ(getGeneralRegister(18), 0); + EXPECT_EQ(getGeneralRegister(19), 0); + EXPECT_EQ(getGeneralRegister(20), 0); + EXPECT_EQ(getGeneralRegister(21), 0); + EXPECT_EQ(getGeneralRegister(22), 0); + EXPECT_EQ(getGeneralRegister(23), 0); + EXPECT_EQ(getGeneralRegister(24), 0); + EXPECT_EQ(getGeneralRegister(25), 0); + EXPECT_EQ(getGeneralRegister(26), 0); + EXPECT_EQ(getGeneralRegister(27), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(30), 0); + EXPECT_EQ(getGeneralRegister(31), 0); + EXPECT_EQ(numTicks_, 2); // 1 insn + 1 for unimplemented final insn + + numTicks_ = 0; + + RUN_RISCV_COMP(R"( + c.nop + c.nop + c.nop + c.nop c.nop )"); + + EXPECT_EQ(getGeneralRegister(0), 0); + EXPECT_EQ(getGeneralRegister(1), 0); + EXPECT_EQ(getGeneralRegister(2), 199840); + EXPECT_EQ(getGeneralRegister(3), 0); + EXPECT_EQ(getGeneralRegister(4), 0); + EXPECT_EQ(getGeneralRegister(5), 0); + EXPECT_EQ(getGeneralRegister(6), 0); + EXPECT_EQ(getGeneralRegister(7), 0); + EXPECT_EQ(getGeneralRegister(8), 0); + EXPECT_EQ(getGeneralRegister(9), 0); + EXPECT_EQ(getGeneralRegister(10), 0); + EXPECT_EQ(getGeneralRegister(11), 0); + EXPECT_EQ(getGeneralRegister(12), 0); + EXPECT_EQ(getGeneralRegister(13), 0); + EXPECT_EQ(getGeneralRegister(14), 0); + EXPECT_EQ(getGeneralRegister(15), 0); + EXPECT_EQ(getGeneralRegister(16), 0); + EXPECT_EQ(getGeneralRegister(17), 0); + EXPECT_EQ(getGeneralRegister(18), 0); + EXPECT_EQ(getGeneralRegister(19), 0); + EXPECT_EQ(getGeneralRegister(20), 0); + EXPECT_EQ(getGeneralRegister(21), 0); + EXPECT_EQ(getGeneralRegister(22), 0); + EXPECT_EQ(getGeneralRegister(23), 0); + EXPECT_EQ(getGeneralRegister(24), 0); + EXPECT_EQ(getGeneralRegister(25), 0); + EXPECT_EQ(getGeneralRegister(26), 0); + EXPECT_EQ(getGeneralRegister(27), 0); + EXPECT_EQ(getGeneralRegister(28), 0); + EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_EQ(getGeneralRegister(30), 0); + EXPECT_EQ(getGeneralRegister(31), 0); + EXPECT_EQ(numTicks_, 6); // 5 insns + 1 for unimplemented final insn } TEST_P(InstCompressed, ebreak) { + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer + std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to buffer + RUN_RISCV_COMP(R"( c.ebreak )"); + + std::cout.rdbuf(sbuf); // Restore cout + EXPECT_THAT(buffer.str(), + HasSubstr("[SimEng:ExceptionHandler] Encountered execution " + "not-yet-implemented exception")); + EXPECT_THAT(buffer.str(), + HasSubstr("[SimEng:ExceptionHandler] 0x0000000000000000: 02 " + "90 00 00 c.ebreak ")); + buffer.str(std::string()); } INSTANTIATE_TEST_SUITE_P(RISCV, InstCompressed, From e40a2369eab59d4687d660c679c0dcd2e897960c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 21 Dec 2023 17:00:36 +0000 Subject: [PATCH 042/115] Minor fixup --- src/include/simeng/arch/riscv/Architecture.hh | 3 +++ test/regression/riscv/instructions/compressed.cc | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 235abaaf35..5a4c232227 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -63,6 +63,9 @@ class Architecture : public arch::Architecture { void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const override; + /** Return a struct contains constants */ + archConstants getConstants() const; + private: /** Retrieve an executionInfo object for the requested instruction. If a * opcode-based override has been defined for the latency and/or diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index c466e82796..e15af7ffff 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -663,8 +663,7 @@ TEST_P(InstCompressed, ebreak) { } INSTANTIATE_TEST_SUITE_P(RISCV, InstCompressed, - ::testing::Values(std::make_tuple(EMULATION, - YAML::Load("{}"))), + ::testing::Values(std::make_tuple(EMULATION, "{}")), paramToString); } // namespace From 38aed448d8c45f49a1bfd194c0f5301253f289a6 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 22 Dec 2023 13:30:03 +0000 Subject: [PATCH 043/115] Update JALR test for better coverage --- test/regression/riscv/instructions/jump.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/regression/riscv/instructions/jump.cc b/test/regression/riscv/instructions/jump.cc index 97d71b84dd..968e03fd99 100644 --- a/test/regression/riscv/instructions/jump.cc +++ b/test/regression/riscv/instructions/jump.cc @@ -6,6 +6,7 @@ using InstJump = RISCVRegressionTest; TEST_P(InstJump, jalr) { RUN_RISCV(R"( + li t1, 4 jalr t0, t1, 12 addi t6, t6, 10 jalr ra, t1, 20 @@ -16,8 +17,8 @@ TEST_P(InstJump, jalr) { EXPECT_EQ(getGeneralRegister(30), 5); EXPECT_EQ(getGeneralRegister(31), 10); EXPECT_EQ(getGeneralRegister(29), 3); - EXPECT_EQ(getGeneralRegister(1), 12); - EXPECT_EQ(getGeneralRegister(5), 4); + EXPECT_EQ(getGeneralRegister(1), 16); + EXPECT_EQ(getGeneralRegister(5), 8); } TEST_P(InstJump, jalrAlias) { From ae95e316f7a26b9f741536e658ac8336ebb07e94 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 22 Dec 2023 14:29:42 +0000 Subject: [PATCH 044/115] Change name of operands array for less ambiguity e.g. which operands, aliases metadata.operands name --- src/include/simeng/arch/riscv/Instruction.hh | 8 +- src/lib/arch/riscv/Instruction.cc | 11 +- src/lib/arch/riscv/Instruction_address.cc | 29 +- src/lib/arch/riscv/Instruction_decode.cc | 11 +- src/lib/arch/riscv/Instruction_execute.cc | 426 ++++++++++--------- 5 files changed, 251 insertions(+), 234 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 1ce0b0cd1a..8b47512370 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -202,7 +202,11 @@ class Instruction : public simeng::Instruction { /** An array of provided operand values. Each entry corresponds to a * `sourceRegisters` entry. */ - std::array operands; + // TODO this name change requires updates of the docs on approval + // developer/arch/supported/aarch64.html#aarch64-adding-execution-behaviour-operands + // TODO update AArch64 to keep both inline and references in docs from RISC-V + // to AArch64 correct + std::array sourceRegValues; /** An array of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ @@ -219,7 +223,7 @@ class Instruction : public simeng::Instruction { // Scheduling /** The number of operands that have not yet had values supplied. Used to * determine execution readiness. */ - short operandsPending = 0; + uint16_t numSourceOperandsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index c4e9afae6e..30a9445ced 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -38,7 +38,8 @@ const span Instruction::getSourceRegisters() const { } const span Instruction::getSourceOperands() const { - return {const_cast(operands.data()), operands.size()}; + return {const_cast(sourceRegValues.data()), + sourceRegValues.size()}; } const span Instruction::getDestinationRegisters() const { @@ -47,7 +48,7 @@ const span Instruction::getDestinationRegisters() const { } bool Instruction::isOperandReady(int index) const { - return static_cast(operands[index]); + return static_cast(sourceRegValues[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { @@ -63,8 +64,8 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { assert(value.size() > 0 && "Attempted to provide an uninitialised RegisterValue"); - operands[i] = value; - operandsPending--; + sourceRegValues[i] = value; + numSourceOperandsPending--; } void Instruction::supplyData(uint64_t address, const RegisterValue& data) { @@ -90,7 +91,7 @@ span Instruction::getData() const { return {memoryData.data(), memoryData.size()}; } -bool Instruction::canExecute() const { return (operandsPending == 0); } +bool Instruction::canExecute() const { return (numSourceOperandsPending == 0); } const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 80da6de036..e4098360d5 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -19,38 +19,41 @@ span Instruction::generateAddresses() { assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[1].get(); + address = sourceRegValues[1].get(); } else if (isLoad() && isAtomic()) { // Load reserved // Metadata operand[1] corresponds to instruction operand[0] assert(metadata.operands[1].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[0].get(); + address = sourceRegValues[0].get(); } else if (isStoreAddress() && isAtomic()) { // Store conditional assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[1].get(); + address = sourceRegValues[1].get(); } else if (isLoad()) { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - // std::cerr << "base val: " << operands[0].get() - // << ", disp: " << metadata.operands[1].mem.disp << std::endl; + // std::cerr << "base val: " << sourceRegValues[0].get() + // << ", disp: " << metadata.sourceRegValues[1].mem.disp << + // std::endl; - address = operands[0].get() + metadata.operands[1].mem.disp; + address = + sourceRegValues[0].get() + metadata.operands[1].mem.disp; } else { - // std::cerr << "mem disp: " << metadata.operands[1].mem.disp << - // std::endl; std::cerr << metadata.operands[1].type << std::endl; + // std::cerr << "mem disp: " << metadata.sourceRegValues[1].mem.disp << + // std::endl; std::cerr << metadata.sourceRegValues[1].type << std::endl; assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); // TODO don't use metadata directly here, extract it into member instruction // variable - address = operands[1].get() + metadata.operands[1].mem.disp; + address = + sourceRegValues[1].get() + metadata.operands[1].mem.disp; } // Atomics @@ -116,7 +119,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_W_RL: [[fallthrough]]; case Opcode::RISCV_LR_W_AQ_RL: { - setMemoryAddresses({{operands[0].get(), 4}}); + setMemoryAddresses({{sourceRegValues[0].get(), 4}}); break; } case Opcode::RISCV_LR_D: @@ -126,7 +129,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_D_RL: [[fallthrough]]; case Opcode::RISCV_LR_D_AQ_RL: { - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{sourceRegValues[0].get(), 8}}); break; } case Opcode::RISCV_SC_W: @@ -136,7 +139,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_W_RL: [[fallthrough]]; case Opcode::RISCV_SC_W_AQ_RL: { - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{sourceRegValues[1].get(), 4}}); break; } case Opcode::RISCV_SC_D: @@ -146,7 +149,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_D_RL: [[fallthrough]]; case Opcode::RISCV_SC_D_AQ_RL: { - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{sourceRegValues[1].get(), 8}}); break; } default: diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 18c024eded..03c7f99d1f 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -150,9 +150,9 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - operands[sourceRegisterCount] = RegisterValue(0, 8); + sourceRegValues[sourceRegisterCount] = RegisterValue(0, 8); } else { - operandsPending++; + numSourceOperandsPending++; } sourceRegisterCount++; @@ -192,9 +192,9 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - operands[sourceRegisterCount] = RegisterValue(0, 8); + sourceRegValues[sourceRegisterCount] = RegisterValue(0, 8); } else { - operandsPending++; + numSourceOperandsPending++; } sourceRegisterCount++; @@ -202,11 +202,12 @@ void Instruction::decode() { // First operand is never MEM type, only check after the first. If register // contains memory address, extract reg number from capstone object + // TODO also extract offset for instruction address? else if (i > 0 && op.type == RISCV_OP_MEM) { // Memory operand sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); sourceRegisterCount++; - operandsPending++; + numSourceOperandsPending++; } } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 991a4cfe25..3e9f1538f8 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -173,9 +173,9 @@ void Instruction::executionNYI() { void Instruction::execute() { assert(!executed_ && "Attempted to execute an instruction more than once"); - assert( - canExecute() && - "Attempted to execute an instruction before all operands were provided"); + assert(canExecute() && + "Attempted to execute an instruction before all source operands were " + "provided"); // Implementation of rv64iamfdc according to the v. 20191213 unprivileged spec @@ -221,19 +221,19 @@ void Instruction::execute() { case Opcode::RISCV_SW: // SW rs1,rs2,imm [[fallthrough]]; case Opcode::RISCV_SD: { // SD rs1,rs2,imm - memoryData[0] = operands[0]; + memoryData[0] = sourceRegValues[0]; break; } case Opcode::RISCV_SLL: { // SLL rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); const int64_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); const int64_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); @@ -241,15 +241,15 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLLW: { // SLLW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); const int32_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits int64_t out = signExtendW(static_cast(rs1 << rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); const int32_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); @@ -257,15 +257,15 @@ void Instruction::execute() { break; } case Opcode::RISCV_SRL: { // SRL rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); @@ -273,15 +273,15 @@ void Instruction::execute() { break; } case Opcode::RISCV_SRLW: { // SRLW rd,rs1,rs2 - const uint32_t rs1 = operands[0].get(); + const uint32_t rs1 = sourceRegValues[0].get(); const uint32_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt - const uint32_t rs1 = operands[0].get(); + const uint32_t rs1 = sourceRegValues[0].get(); const uint32_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); @@ -289,15 +289,15 @@ void Instruction::execute() { break; } case Opcode::RISCV_SRA: { // SRA rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); const int64_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); const int64_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); @@ -305,15 +305,15 @@ void Instruction::execute() { break; } case Opcode::RISCV_SRAW: { // SRAW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); const int32_t rs2 = - operands[1].get() & 63; // Only use lowest 6 bits + sourceRegValues[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); const int32_t shamt = metadata.operands[2].imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); @@ -321,43 +321,43 @@ void Instruction::execute() { break; } case Opcode::RISCV_ADD: { // ADD rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDW: { // ADDW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); - const int32_t rs2 = operands[1].get(); + const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs2 = sourceRegValues[1].get(); int64_t out = static_cast(static_cast(rs1 + rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = metadata.operands[2].imm; uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); const int32_t imm = metadata.operands[2].imm; uint64_t out = signExtendW(rs1 + imm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUB: { // SUB rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); uint64_t out = static_cast(rs1 - rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUBW: { // SUBW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); - const int32_t rs2 = operands[1].get(); + const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs2 = sourceRegValues[1].get(); int64_t out = static_cast(static_cast(rs1 - rs2)); results[0] = RegisterValue(out, 8); break; @@ -377,50 +377,50 @@ void Instruction::execute() { break; } case Opcode::RISCV_XOR: { // XOR rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); uint64_t out = static_cast(rs1 ^ rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t imm = metadata.operands[2].imm; uint64_t out = static_cast(rs1 ^ imm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_OR: { // OR rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); uint64_t out = static_cast(rs1 | rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t imm = metadata.operands[2].imm; uint64_t out = static_cast(rs1 | imm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AND: { // AND rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); uint64_t out = static_cast(rs1 & rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t imm = metadata.operands[2].imm; uint64_t out = static_cast(rs1 & imm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLT: { // SLT rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -429,8 +429,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTU: { // SLTU rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -439,7 +439,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); const int64_t imm = metadata.operands[2].imm; if (rs1 < imm) { results[0] = RegisterValue(static_cast(1), 8); @@ -449,7 +449,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t imm = static_cast(metadata.operands[2].imm); if (rs1 < imm) { results[0] = RegisterValue(static_cast(1), 8); @@ -459,8 +459,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BEQ: { // BEQ rs1,rs2,imm - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 == rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -472,8 +472,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BNE: { // BNE rs1,rs2,imm - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 != rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -486,8 +486,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLT: { // BLT rs1,rs2,imm - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -499,8 +499,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLTU: { // BLTU rs1,rs2,imm - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -512,8 +512,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGE: { // BGE rs1,rs2,imm - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -525,8 +525,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGEU: { // BGEU rs1,rs2,imm - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + metadata.operands[2].imm; // Set LSB of result to 0 @@ -546,7 +546,7 @@ void Instruction::execute() { } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm branchAddress_ = - (operands[0].get() + metadata.operands[2].imm) & + (sourceRegValues[0].get() + metadata.operands[2].imm) & ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); @@ -609,7 +609,7 @@ void Instruction::execute() { // if not raise address-misaligned/access-fault exception // TODO use aq and rl bits to prevent reordering with other memory // operations - memoryData[0] = operands[0]; + memoryData[0] = sourceRegValues[0]; results[0] = RegisterValue(static_cast(0), 8); break; } @@ -623,7 +623,7 @@ void Instruction::execute() { // TODO raise address misaligned or access-fault errors // TODO account for AQ and RL bits int64_t rd = signExtendW(memoryData[0].get()); - int32_t rs2 = operands[0].get(); + int32_t rs2 = sourceRegValues[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -633,7 +633,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOSWAP_D_RL: case Opcode::RISCV_AMOSWAP_D_AQ_RL: { uint64_t rd = memoryData[0].get(); - uint64_t rs2 = operands[0].get(); + uint64_t rs2 = sourceRegValues[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -644,7 +644,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd + operands[0].get()); + memoryData[0] = + static_cast(rd + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOADD_D: // AMOADD.D rd,rs1,rs2 @@ -653,7 +654,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd + operands[0].get()); + memoryData[0] = + static_cast(rd + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOAND_W: // AMOAND.W rd,rs1,rs2 @@ -662,7 +664,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd & operands[0].get()); + memoryData[0] = + static_cast(rd & sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOAND_D: // AMOAND.D rd,rs1,rs2 @@ -671,7 +674,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd & operands[0].get()); + memoryData[0] = + static_cast(rd & sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOOR_W: // AMOOR.W rd,rs1,rs2 @@ -680,7 +684,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd | operands[0].get()); + memoryData[0] = + static_cast(rd | sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOOR_D: // AMOOR.D rd,rs1,rs2 @@ -689,7 +694,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd | operands[0].get()); + memoryData[0] = + static_cast(rd | sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOXOR_W: // AMOXOR.W rd,rs1,rs2 @@ -698,7 +704,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd ^ operands[0].get()); + memoryData[0] = + static_cast(rd ^ sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOXOR_D: // AMOXOR.D rd,rs1,rs2 @@ -707,7 +714,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd ^ operands[0].get()); + memoryData[0] = + static_cast(rd ^ sourceRegValues[0].get()); break; } @@ -716,8 +724,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMIN_W_RL: case Opcode::RISCV_AMOMIN_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = - std::min(memoryData[0].get(), operands[0].get()); + memoryData[0] = std::min(memoryData[0].get(), + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOMIN_D: // AMOMIN.D rd,rs1,rs2 @@ -727,7 +735,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::min(rd, operands[0].get())); + static_cast(std::min(rd, sourceRegValues[0].get())); break; } case Opcode::RISCV_AMOMINU_W: // AMOMINU.W rd,rs1,rs2 @@ -735,8 +743,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMINU_W_RL: case Opcode::RISCV_AMOMINU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = - std::min(memoryData[0].get(), operands[0].get()); + memoryData[0] = std::min(memoryData[0].get(), + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOMINU_D: // AMOMINU.D rd,rs1,rs2 @@ -745,8 +753,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMINU_D_AQ_RL: { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(std::min(rd, operands[0].get())); + memoryData[0] = static_cast( + std::min(rd, sourceRegValues[0].get())); break; } @@ -755,8 +763,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAX_W_RL: case Opcode::RISCV_AMOMAX_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = - std::max(memoryData[0].get(), operands[0].get()); + memoryData[0] = std::max(memoryData[0].get(), + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOMAX_D: // AMOMAX.D rd,rs1,rs2 @@ -766,7 +774,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::max(rd, operands[0].get())); + static_cast(std::max(rd, sourceRegValues[0].get())); break; } case Opcode::RISCV_AMOMAXU_W: // AMOMAXU.W rd,rs1,rs2 @@ -774,8 +782,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAXU_W_RL: case Opcode::RISCV_AMOMAXU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = - std::max(memoryData[0].get(), operands[0].get()); + memoryData[0] = std::max(memoryData[0].get(), + sourceRegValues[0].get()); break; } case Opcode::RISCV_AMOMAXU_D: // AMOMAXU.D rd,rs1,rs2 @@ -784,50 +792,50 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAXU_D_AQ_RL: { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(std::max(rd, operands[0].get())); + memoryData[0] = static_cast( + std::max(rd, sourceRegValues[0].get())); break; } // Integer multiplication division extension (M) case Opcode::RISCV_MUL: { // MUL rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(static_cast(rs1 * rs2), 8); break; } // case Opcode::RISCV_MULH: {//MULH rd,rs1,rs2 // return executionNYI(); // - // const int64_t rs1 = operands[0].get(); - // const int64_t rs2 = operands[1].get(); + // const int64_t rs1 = sourceRegValues[0].get(); + // const int64_t rs2 = sourceRegValues[1].get(); // results[0] = RegisterValue(mulhiss(rs1, rs2); // break; // } case Opcode::RISCV_MULHU: { // MULHU rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(mulhiuu(rs1, rs2), 8); break; } // case Opcode::RISCV_MULHSU: {//MULHSU rd,rs1,rs2 // return executionNYI(); // - // const int64_t rs1 = operands[0].get(); - // const uint64_t rs2 = operands[1].get(); + // const int64_t rs1 = sourceRegValues[0].get(); + // const uint64_t rs2 = sourceRegValues[1].get(); // results[0] = RegisterValue(mulhisu(rs1, rs2); // break; // } case Opcode::RISCV_MULW: { // MULW rd,rs1,rs2 - const uint32_t rs1 = operands[0].get(); - const uint32_t rs2 = operands[1].get(); + const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(signExtendW(rs1 * rs2), 8); break; } case Opcode::RISCV_DIV: { // DIV rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -840,8 +848,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVW: { // DIVW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); - const int32_t rs2 = operands[1].get(); + const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -855,8 +863,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVU: { // DIVU rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -866,8 +874,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVUW: { // DIVUW rd,rs1,rs2 - const uint32_t rs1 = operands[0].get(); - const uint32_t rs2 = operands[1].get(); + const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -878,8 +886,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REM: { // REM rd,rs1,rs2 - const int64_t rs1 = operands[0].get(); - const int64_t rs2 = operands[1].get(); + const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(rs1), 8); @@ -892,8 +900,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMW: { // REMW rd,rs1,rs2 - const int32_t rs1 = operands[0].get(); - const int32_t rs2 = operands[1].get(); + const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -907,8 +915,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMU: { // REMU rd,rs1,rs2 - const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = operands[1].get(); + const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(rs1, 8); @@ -918,8 +926,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMUW: { // REMUW rd,rs1,rs2 - const uint32_t rs1 = operands[0].get(); - const uint32_t rs2 = operands[1].get(); + const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs2 = sourceRegValues[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -975,11 +983,11 @@ void Instruction::execute() { // Single-Precision Floating-Point (F) // Double-Precision Floating-Point (D) case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm - memoryData[0] = operands[0]; + memoryData[0] = sourceRegValues[0]; break; } case Opcode::RISCV_FSW: { // FSW rs1,rs2,imm - memoryData[0] = operands[0]; + memoryData[0] = sourceRegValues[0]; break; } case Opcode::RISCV_FLD: { // FLD rd,rs1,imm @@ -995,8 +1003,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_D: { // FADD.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(rs1 + rs2, 8); }); @@ -1005,8 +1013,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_S: { // FADD.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(rs1 + rs2), 8); }); @@ -1015,8 +1023,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_D: { // FSUB.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(rs1 - rs2, 8); }); @@ -1026,8 +1034,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_S: { // FSUB.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(rs1 - rs2), 8); }); @@ -1037,8 +1045,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_D: { // FDIV.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(rs1 / rs2, 8); }); @@ -1048,8 +1056,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_S: { // FDIV.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(rs1 / rs2), 8); }); @@ -1059,8 +1067,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_D: { // FMUL.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(rs1 * rs2, 8); }); @@ -1070,8 +1078,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_S: { // FMUL.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(rs1 * rs2), 8); }); @@ -1081,7 +1089,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_D: { // FSQRT.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); const double sqrtAns = sqrt(rs1); @@ -1097,7 +1105,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_S: { // FSQRT.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); const float sqrtAns = sqrtf(rs1); @@ -1112,8 +1120,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMIN_D: { // FMIN.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); // cpp fmin reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1128,8 +1136,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMIN_S: { // FMIN.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); // Comments regarding fminf similar to RISCV_FMIN_D if (rs1 == 0 && rs2 == 0) { @@ -1142,8 +1150,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMAX_D: { // FMAX.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); // cpp fmax reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1157,8 +1165,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMAX_S: { // FMAX.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); // Comments regarding fmaxf similar to RISCV_FMAX_D if (rs1 == 0 && rs2 == 0) { @@ -1178,9 +1186,9 @@ void Instruction::execute() { // the addend is a quiet NaN. setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); - const double rs3 = operands[2].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); + const double rs3 = sourceRegValues[2].get(); results[0] = RegisterValue(fma(rs1, rs2, rs3), 8); }); @@ -1190,9 +1198,9 @@ void Instruction::execute() { case Opcode::RISCV_FMADD_S: { // FMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); - const float rs3 = checkNanBox(operands[2]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs3 = checkNanBox(sourceRegValues[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1206,9 +1214,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_D: { // FNMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); - const double rs3 = operands[2].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); + const double rs3 = sourceRegValues[2].get(); results[0] = RegisterValue(-(rs1 * rs2) + rs3, 8); }); @@ -1218,9 +1226,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_S: { // FNMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); - const float rs3 = checkNanBox(operands[2]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs3 = checkNanBox(sourceRegValues[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1234,9 +1242,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_D: { // FMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); - const double rs3 = operands[2].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); + const double rs3 = sourceRegValues[2].get(); results[0] = RegisterValue((rs1 * rs2) - rs3, 8); }); @@ -1246,9 +1254,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_S: { // FMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); - const float rs3 = checkNanBox(operands[2]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs3 = checkNanBox(sourceRegValues[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1262,9 +1270,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_D: { // FNMADD.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); - const double rs3 = operands[2].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); + const double rs3 = sourceRegValues[2].get(); results[0] = RegisterValue(-(rs1 * rs2) - rs3, 8); }); @@ -1274,9 +1282,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_S: { // FNMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); - const float rs3 = checkNanBox(operands[2]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs3 = checkNanBox(sourceRegValues[2]); // Some implementations return -NaN if certain inputs are NaN but spec // requires +NaN. Ensure this happens @@ -1292,7 +1300,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_L: { // FCVT.D.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1302,7 +1310,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_W: { // FCVT.D.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1312,7 +1320,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_L: { // FCVT.S.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = operands[0].get(); + const int64_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1322,7 +1330,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_W: { // FCVT.S.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = operands[0].get(); + const int32_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1332,7 +1340,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_D: { // FCVT.W.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1346,7 +1354,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_S: { // FCVT.W.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1360,7 +1368,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_D: { // FCVT.L.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1374,7 +1382,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_S: { // FCVT.L.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1388,7 +1396,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_D: { // FCVT.WU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1407,7 +1415,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_S: { // FCVT.WU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1426,7 +1434,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_D: { // FCVT.LU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1445,7 +1453,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_S: { // FCVT.LU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1464,7 +1472,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_LU: { // FCVT.D.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1474,7 +1482,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_WU: { // FCVT.D.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = operands[0].get(); + const uint32_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1484,7 +1492,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_LU: { // FCVT.S.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1494,7 +1502,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_WU: { // FCVT.S.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = operands[0].get(); + const uint32_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1503,50 +1511,50 @@ void Instruction::execute() { } case Opcode::RISCV_FCVT_D_S: { // FCVT.D.S rd,rs1 - const float rs1 = checkNanBox(operands[0]); + const float rs1 = checkNanBox(sourceRegValues[0]); results[0] = RegisterValue((double)rs1, 8); break; } case Opcode::RISCV_FCVT_S_D: { // FCVT.S.D rd,rs1 - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } case Opcode::RISCV_FSGNJ_D: { // FSGNJ.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(std::copysign(rs1, rs2), 8); break; } case Opcode::RISCV_FSGNJ_S: { // FSGNJ.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, rs2)), 8); break; } case Opcode::RISCV_FSGNJN_D: { // FSGNJN.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); break; } case Opcode::RISCV_FSGNJN_S: { // FSGNJN.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, -rs2)), 8); break; } case Opcode::RISCV_FSGNJX_D: { // FSGNJX.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); const double xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1554,8 +1562,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FSGNJX_S: { // FSGNJX.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); const float xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1564,25 +1572,25 @@ void Instruction::execute() { } case Opcode::RISCV_FMV_D_X: { // FMV.D.X rd,rs1 - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_X_D: { // FMV.X.D rd,rs1 - const double rs1 = operands[0].get(); + const double rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_W_X: { // FMV.W.X rd,rs1 - const float rs1 = operands[0].get(); + const float rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(NanBoxFloat(rs1), 8); break; } case Opcode::RISCV_FMV_X_W: { // FMV.X.W rd,rs1 - const uint64_t rs1 = operands[0].get(); + const uint64_t rs1 = sourceRegValues[0].get(); results[0] = RegisterValue(signExtendW(rs1), 8); break; @@ -1601,8 +1609,8 @@ void Instruction::execute() { // either input is a signaling NaN. Qemu doesn't seem to set CSR flags // with sNANs so unsure of correct implementation. Also require proper // Zicsr implementation - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1612,8 +1620,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FEQ_S: { // FEQ.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1623,8 +1631,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_D: { // FLT.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1637,8 +1645,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_S: { // FLT.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1651,8 +1659,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_D: { // FLE.D rd,rs1,rs2 - const double rs1 = operands[0].get(); - const double rs2 = operands[1].get(); + const double rs1 = sourceRegValues[0].get(); + const double rs2 = sourceRegValues[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1665,8 +1673,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_S: { // FLE.S rd,rs1,rs2 - const float rs1 = checkNanBox(operands[0]); - const float rs2 = checkNanBox(operands[1]); + const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs2 = checkNanBox(sourceRegValues[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete From f0370247c7c45b4de72070495c67bc62672df1f7 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 22 Dec 2023 19:00:39 +0000 Subject: [PATCH 045/115] Create Instruction immediate field to prevent usage of metadata outside of decode --- src/include/simeng/arch/riscv/Instruction.hh | 6 +- src/lib/arch/riscv/InstructionMetadata.cc | 9 +-- src/lib/arch/riscv/Instruction_address.cc | 20 ++--- src/lib/arch/riscv/Instruction_decode.cc | 8 +- src/lib/arch/riscv/Instruction_execute.cc | 80 ++++++++------------ 5 files changed, 49 insertions(+), 74 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 8b47512370..8597d92ccb 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -208,6 +208,9 @@ class Instruction : public simeng::Instruction { // to AArch64 correct std::array sourceRegValues; + /** Extracted value of current immediate from metadata */ + int64_t imm = 0; + /** An array of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ std::array results; @@ -260,9 +263,6 @@ class Instruction : public simeng::Instruction { /** Is this a floating point <-> integer convert operation? */ bool isConvert_ = false; - /** Extracted value of current immediate from metadata */ - uint32_t c_imm = 0; - // Memory /** Set the accessed memory addresses, and create a corresponding memory data * vector. */ diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index c40933ce37..a6c18800a6 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -549,13 +549,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { includeZeroRegisterPosOne(); - // operands[2] = insn.detail->riscv.operands[1]; - // - // operands[1].type = RISCV_OP_REG; - // operands[1].reg = 1; - // - // operandCount = 3; - break; case Opcode::RISCV_C_ADDI16SP: // Opcode shared with C.LUI but has Rd = x2 @@ -713,6 +706,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { operands[0].type = RISCV_OP_REG; operands[0].reg = 1; + operandCount = 2; + break; case Opcode::RISCV_C_ADDIW: // TODO rv64 ONLY, make check for this diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index e4098360d5..a79d592313 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -15,14 +15,14 @@ span Instruction::generateAddresses() { uint64_t address; if (isLoad() && isStoreAddress() && isAtomic()) { // Atomics - // Metadata operand[2] corresponds to instruction operand[1] + // Metadata operand[2] corresponds to instruction sourceRegValues[1] assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); address = sourceRegValues[1].get(); } else if (isLoad() && isAtomic()) { // Load reserved - // Metadata operand[1] corresponds to instruction operand[0] + // Metadata operand[1] corresponds to instruction sourceRegValues[0] assert(metadata.operands[1].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); @@ -37,23 +37,13 @@ span Instruction::generateAddresses() { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - // std::cerr << "base val: " << sourceRegValues[0].get() - // << ", disp: " << metadata.sourceRegValues[1].mem.disp << - // std::endl; - - address = - sourceRegValues[0].get() + metadata.operands[1].mem.disp; + address = sourceRegValues[0].get() + imm; } else { - // std::cerr << "mem disp: " << metadata.sourceRegValues[1].mem.disp << - // std::endl; std::cerr << metadata.sourceRegValues[1].type << std::endl; - assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); - // TODO don't use metadata directly here, extract it into member instruction - // variable - address = - sourceRegValues[1].get() + metadata.operands[1].mem.disp; + + address = sourceRegValues[1].get() + imm; } // Atomics diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 03c7f99d1f..8d8067e320 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -132,7 +132,7 @@ void Instruction::decode() { isAtomic_ = true; } - // Extract explicit register accesses, ignore immediates until execute + // Extract explicit register accesses and immediates for (size_t i = 0; i < metadata.operandCount; i++) { const auto& op = metadata.operands[i]; @@ -206,9 +206,15 @@ void Instruction::decode() { else if (i > 0 && op.type == RISCV_OP_MEM) { // Memory operand sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); + imm = op.mem.disp; sourceRegisterCount++; numSourceOperandsPending++; } + + // First operands never immediate + else if (i > 0 && op.type == RISCV_OP_IMM) { + imm = op.imm; + } } if ((Opcode::RISCV_SLL <= metadata.opcode && diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 3e9f1538f8..419f244430 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -234,8 +234,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt const int64_t rs1 = sourceRegValues[0].get(); - const int64_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); results[0] = RegisterValue(out, 8); break; @@ -250,8 +249,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt const int32_t rs1 = sourceRegValues[0].get(); - const int32_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const int32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); results[0] = RegisterValue(out, 8); break; @@ -266,8 +264,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const uint64_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -282,8 +279,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt const uint32_t rs1 = sourceRegValues[0].get(); - const uint32_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const uint32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); results[0] = RegisterValue(out, 8); break; @@ -298,8 +294,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt const int64_t rs1 = sourceRegValues[0].get(); - const int64_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -314,8 +309,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt const int32_t rs1 = sourceRegValues[0].get(); - const int32_t shamt = - metadata.operands[2].imm & 63; // Only use lowest 6 bits + const int32_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -336,15 +330,15 @@ void Instruction::execute() { } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = metadata.operands[2].imm; + const uint64_t rs2 = imm; uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm const int32_t rs1 = sourceRegValues[0].get(); - const int32_t imm = metadata.operands[2].imm; - uint64_t out = signExtendW(rs1 + imm); + const int32_t sourceImm = imm; + uint64_t out = signExtendW(rs1 + sourceImm); results[0] = RegisterValue(out, 8); break; } @@ -362,16 +356,14 @@ void Instruction::execute() { results[0] = RegisterValue(out, 8); break; } - case Opcode::RISCV_LUI: { // LUI rd,imm - uint64_t out = signExtendW(metadata.operands[1].imm - << 12); // Shift into upper 20 bits + case Opcode::RISCV_LUI: { // LUI rd,imm + uint64_t out = signExtendW(imm << 12); // Shift into upper 20 bits results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AUIPC: { // AUIPC rd,imm const int64_t pc = instructionAddress_; - const int64_t uimm = signExtendW(metadata.operands[1].imm - << 12); // Shift into upper 20 bits + const int64_t uimm = signExtendW(imm << 12); // Shift into upper 20 bits uint64_t out = static_cast(pc + uimm); results[0] = RegisterValue(out, 8); break; @@ -385,8 +377,8 @@ void Instruction::execute() { } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t imm = metadata.operands[2].imm; - uint64_t out = static_cast(rs1 ^ imm); + const uint64_t sourceImm = imm; + uint64_t out = static_cast(rs1 ^ sourceImm); results[0] = RegisterValue(out, 8); break; } @@ -399,8 +391,8 @@ void Instruction::execute() { } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t imm = metadata.operands[2].imm; - uint64_t out = static_cast(rs1 | imm); + const uint64_t sourceImm = imm; + uint64_t out = static_cast(rs1 | sourceImm); results[0] = RegisterValue(out, 8); break; } @@ -413,8 +405,8 @@ void Instruction::execute() { } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t imm = metadata.operands[2].imm; - uint64_t out = static_cast(rs1 & imm); + const uint64_t sourceImm = imm; + uint64_t out = static_cast(rs1 & sourceImm); results[0] = RegisterValue(out, 8); break; } @@ -440,8 +432,8 @@ void Instruction::execute() { } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm const int64_t rs1 = sourceRegValues[0].get(); - const int64_t imm = metadata.operands[2].imm; - if (rs1 < imm) { + const int64_t sourceImm = imm; + if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); } else { results[0] = RegisterValue(static_cast(0), 8); @@ -450,8 +442,8 @@ void Instruction::execute() { } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t imm = static_cast(metadata.operands[2].imm); - if (rs1 < imm) { + const uint64_t sourceImm = static_cast(imm); + if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); } else { results[0] = RegisterValue(static_cast(0), 8); @@ -462,8 +454,7 @@ void Instruction::execute() { const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 == rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -475,8 +466,7 @@ void Instruction::execute() { const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 != rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { // Increase by instruction size to account for compressed instructions @@ -489,8 +479,7 @@ void Instruction::execute() { const int64_t rs1 = sourceRegValues[0].get(); const int64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -502,8 +491,7 @@ void Instruction::execute() { const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -515,8 +503,7 @@ void Instruction::execute() { const int64_t rs1 = sourceRegValues[0].get(); const int64_t rs2 = sourceRegValues[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -528,8 +515,7 @@ void Instruction::execute() { const uint64_t rs1 = sourceRegValues[0].get(); const uint64_t rs2 = sourceRegValues[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + - metadata.operands[2].imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -537,17 +523,15 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_JAL: { // JAL rd,imm - branchAddress_ = instructionAddress_ + - metadata.operands[1].imm; // Set LSB of result to 0 + case Opcode::RISCV_JAL: { // JAL rd,imm + branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm - branchAddress_ = - (sourceRegValues[0].get() + metadata.operands[2].imm) & - ~1; // Set LSB of result to 0 + branchAddress_ = (sourceRegValues[0].get() + imm) & + ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; From 6242e854689ed45651e95008184ab77e841cef47 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 22 Dec 2023 19:38:52 +0000 Subject: [PATCH 046/115] Cleanup --- src/include/simeng/arch/riscv/ArchInfo.hh | 9 +++++ src/include/simeng/arch/riscv/Architecture.hh | 9 ----- src/include/simeng/arch/riscv/Instruction.hh | 3 -- src/lib/arch/riscv/Instruction.cc | 2 -- src/lib/arch/riscv/InstructionMetadata.cc | 34 ++++++++----------- src/lib/arch/riscv/InstructionMetadata.hh | 16 +++++++-- test/regression/riscv/instructions/csr.cc | 18 ---------- 7 files changed, 37 insertions(+), 54 deletions(-) delete mode 100644 test/regression/riscv/instructions/csr.cc diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index b721984ae7..25c22e7ead 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -19,6 +19,15 @@ typedef enum riscv_sysreg { } riscv_sysreg; +struct constantsPool { + const uint8_t alignMask = 0x3; + const uint8_t alignMaskCompressed = 0x1; + const uint8_t bytesLimit = 4; + const uint8_t bytesLimitCompressed = 2; + const uint8_t byteLength64 = 8; + const uint8_t byteLength32 = 4; +}; + /** A class to hold and generate riscv specific architecture configuration * options. */ class ArchInfo : public simeng::arch::ArchInfo { diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 5a4c232227..a3c83897ef 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -14,15 +14,6 @@ namespace simeng { namespace arch { namespace riscv { -struct constantsPool { - const uint8_t alignMask = 0x3; - const uint8_t alignMaskCompressed = 0x1; - const uint8_t bytesLimit = 4; - const uint8_t bytesLimitCompressed = 2; - const uint8_t byteLength64 = 8; - const uint8_t byteLength32 = 4; -}; - struct archConstants { uint8_t alignMask; uint8_t bytesLimit; /* Minimum bytes the decoder needs to process */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 8597d92ccb..a8cd1a7787 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -172,9 +172,6 @@ class Instruction : public simeng::Instruction { * automatically supplied as zero. */ static const Register ZERO_REGISTER; - static const Register RA_REGISTER; - static const Register SP_REGISTER; - private: /** The maximum number of source registers any supported RISC-V instruction * can have. */ diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 30a9445ced..754f11f565 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -11,8 +11,6 @@ namespace arch { namespace riscv { const Register Instruction::ZERO_REGISTER = {RegisterType::GENERAL, 0}; -const Register Instruction::RA_REGISTER = {RegisterType::GENERAL, 1}; -const Register Instruction::SP_REGISTER = {RegisterType::GENERAL, 2}; Instruction::Instruction(const Architecture& architecture, const InstructionMetadata& metadata) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index a6c18800a6..2d7b7c0cf1 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -465,7 +465,6 @@ void InstructionMetadata::createMemOpPosOne() { cs_riscv_op temp; temp.type = RISCV_OP_MEM; - temp.imm = operands[1].imm; // temp.mem.base = operands[2].reg; temp.mem.disp = operands[1].imm; @@ -488,40 +487,37 @@ void InstructionMetadata::setLength(uint8_t size) { } } void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { - // std::cerr << ": " << insn.mnemonic << " " << operandStr << std::endl; if (len != INSTR_LENGTH::IL_16B) { return; } - // std::cerr << std::endl - // << "COMPRESSED:: " << insn.address << ":" << insn.mnemonic << " - // " - // << operandStr << std::endl; - switch (insn.opcode) { case Opcode::RISCV_C_JR: - // jalr x0, 0(rs1) + // jalr x0, 0(rs1) // trap if rs1 = zero + // C.JR Rs, _, _ -> JALR x0, Rs, 0 opcode = Opcode::RISCV_JALR; - // TODO repeat logic so that mnemonic can remain for help when debugging - // Change mnemonic to allow pseudoinstruction code to work - strcpy(mnemonic, reinterpret_cast("jr")); + + operands[0].type = RISCV_OP_REG; + operands[0].reg = 1; + + operands[1] = insn.detail->riscv.operands[0]; + + operands[2].type = RISCV_OP_IMM; + operands[2].imm = 0; + + operandCount = 3; + break; case Opcode::RISCV_C_MV: // add rd, x0, rs2 - // trap if rs2 = zero. rs2 == zero corresponds to C.JR - // rs2==zero and rd == zero are hints + // trap if rs2 = zero. rs2 == zero corresponds to C.JR + // rs2==zero and rd == zero are hints // C.MV rd, rs2, _ -> ADD rd, zero, rs2 opcode = Opcode::RISCV_ADD; includeZeroRegisterPosOne(); - // operands[2] = insn.detail->riscv.operands[1]; - // - // operands[1].type = RISCV_OP_REG; - // operands[1].reg = 1; - // - // operandCount = 3; break; case Opcode::RISCV_C_LDSP: { // TODO valid for RV64 only. Make this check diff --git a/src/lib/arch/riscv/InstructionMetadata.hh b/src/lib/arch/riscv/InstructionMetadata.hh index ffaed58e57..7904289c2a 100644 --- a/src/lib/arch/riscv/InstructionMetadata.hh +++ b/src/lib/arch/riscv/InstructionMetadata.hh @@ -96,6 +96,10 @@ struct InstructionMetadata { * instruction. */ void alterPseudoInstructions(const cs_insn& insn); + /** Detect compressed instructions and update metadata to match the + * non-compressed instruction expansion. */ + void convertCompressedInstruction(const cs_insn& insn); + /** Flag the instruction as aliasNYI due to a detected unsupported alias. */ void aliasNYI(); @@ -107,6 +111,15 @@ struct InstructionMetadata { * Use register zero as operands[0] and immediate value as operands[2] */ void includeZeroRegisterPosZero(); + /** RISC-V helper function + * Duplicate operands[0] and move operands[1] to operands[2] */ + void duplicateFirstOp(); + + /** RISC-V helper function + * Combine operands[1] and operands[2] which are of type imm and reg + * respectively into a single mem type operand */ + void createMemOpPosOne(); + /** The current exception state of this instruction. */ InstructionException metadataException_ = InstructionException::None; @@ -115,9 +128,6 @@ struct InstructionMetadata { /** Set the byte length of instruction */ void setLength(uint8_t size); - void convertCompressedInstruction(const cs_insn& insn); - void duplicateFirstOp(); - void createMemOpPosOne(); }; } // namespace riscv diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc deleted file mode 100644 index 28d3f99a5f..0000000000 --- a/test/regression/riscv/instructions/csr.cc +++ /dev/null @@ -1,18 +0,0 @@ -#include "RISCVRegressionTest.hh" - -namespace { - -using InstCsr = RISCVRegressionTest; - -TEST_P(InstCsr, cycle) { - RUN_RISCV(R"( - csrrw t1, frm, t1 - )"); -} - -INSTANTIATE_TEST_SUITE_P(RISCV, InstCsr, - ::testing::Values(std::make_tuple(EMULATION, - YAML::Load("{}"))), - paramToString); - -} // namespace From 60afac6f1264824e8761fc09d88aafe56b1eff00 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 22 Dec 2023 20:41:27 +0000 Subject: [PATCH 047/115] Initial OoO debug, prevent predecoding too many bytes --- src/include/simeng/arch/riscv/Architecture.hh | 4 +-- src/lib/arch/riscv/Architecture.cc | 16 ++++++++++ src/lib/arch/riscv/InstructionMetadata.cc | 2 ++ src/lib/arch/riscv/Instruction_decode.cc | 3 ++ src/lib/arch/riscv/Instruction_execute.cc | 3 ++ src/lib/pipeline/FetchUnit.cc | 30 +++++++++++++++++++ src/tools/simeng/main.cc | 2 ++ 7 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index a3c83897ef..ebde07837f 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -27,8 +27,8 @@ class Architecture : public arch::Architecture { ryml::ConstNodeRef config = config::SimInfo::getConfig()); ~Architecture(); /** Pre-decode instruction memory into a macro-op of `Instruction` - * instances. Returns the number of bytes consumed to produce it (always 4), - * and writes into the supplied macro-op vector. */ + * instances. Returns the number of bytes consumed to produce it (0 if + * failure), and writes into the supplied macro-op vector. */ uint8_t predecode(const void* ptr, uint8_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const override; diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 54819f1cfd..480104891c 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -160,6 +160,9 @@ Architecture::~Architecture() { uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { + std::cerr << "predecode at address: " << std::hex << instructionAddress + << std::dec << std::endl; + // Check that instruction address is 4-byte aligned as required by RISC-V // 2-byte when Compressed ISA is supported if (instructionAddress & constants_.alignMask) { @@ -175,6 +178,8 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, return 1; } + std::cerr << "predecode bytes avail " << (int)bytesAvailable << std::endl; + assert(bytesAvailable >= constants_.bytesLimit && "Fewer than bytes limit supplied to RISC-V decoder"); @@ -214,14 +219,25 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, iter = decodeCache.insert({insn, newInsn}).first; } + if (iter->second.getMetadata().lenBytes > bytesAvailable) { + // Too many bytes read. BAIL + std::cerr << "TOO MANY BYTES READ" << std::endl; + return 0; + } + output.resize(1); auto& uop = output[0]; // Retrieve the cached instruction and write to output uop = std::make_shared(iter->second); + std::cerr << "setInstructionAddress: " << std::hex << instructionAddress + << std::dec << std::endl; + uop->setInstructionAddress(instructionAddress); + std::cerr << std::hex << instructionAddress << std::dec << std::endl; + return iter->second.getMetadata().lenBytes; } diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 2d7b7c0cf1..c043f0e243 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -16,6 +16,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitDestinationCount(insn.detail->regs_write_count), operandCount(insn.detail->riscv.op_count) { // std::memcpy(encoding, insn.bytes, sizeof(encoding)); + std::cerr << "metadata insn size" << insn.size << std::endl; + setLength(insn.size); std::memset(encoding, 0, 4); std::memcpy(encoding, insn.bytes, insn.size); diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 8d8067e320..5d97b81e87 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -65,6 +65,9 @@ Register csRegToRegister(unsigned int reg) { *****************/ void Instruction::decode() { if (metadata.id == RISCV_INS_INVALID) { + std::cerr << "INVALID at " << std::hex << instructionAddress_ << std::dec + << std::endl; + exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; return; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 419f244430..d18b5df28f 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,6 +179,9 @@ void Instruction::execute() { // Implementation of rv64iamfdc according to the v. 20191213 unprivileged spec + // std::cerr << std::hex << instructionAddress_ << " " << metadata.mnemonic + // << " " << metadata.operandStr << std::dec << std::endl; + executed_ = true; switch (metadata.opcode) { case Opcode::RISCV_LB: { // LB rd,rs1,imm diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index fc0bbedc12..777850516d 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -73,6 +73,8 @@ void FetchUnit::tick() { // Fetch buffer is empty, so start from the PC blockAddress = pc_ & blockMask_; bufferOffset = pc_ - blockAddress; + std::cerr << "76 bufferOffset: " << (int)bufferOffset << " = " << (int)pc_ + << " - " << (int)blockAddress << std::endl; } // Find fetched memory that matches the desired block @@ -97,7 +99,13 @@ void FetchUnit::tick() { std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, blockSize_ - bufferOffset); + std::cerr << "pre101: " << (int)bufferedBytes_ << " += " << (int)blockSize_ + << " - " << (int)bufferOffset << std::endl; + + // TODO can bufferedBytes_ go above the block size? bufferedBytes_ += blockSize_ - bufferOffset; + std::cerr << "101: " << (int)bufferedBytes_ << std::endl; + buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. bufferOffset = 0; @@ -117,8 +125,12 @@ void FetchUnit::tick() { auto bytesRead = isa_.predecode(buffer + bufferOffset, bufferedBytes_, pc_, macroOp); + std::cerr << "Bytes read = " << (int)bytesRead << std::endl; + // If predecode fails, bail and wait for more data if (bytesRead == 0) { + std::cerr << "BAIL" << std::endl; + assert(bufferedBytes_ < isa_.getMaxInstructionSize() && "unexpected predecode failure"); break; @@ -163,18 +175,32 @@ void FetchUnit::tick() { loopBufferState_ = LoopBufferState::FILLING; } + if (bytesRead > bufferedBytes_) { + std::cerr << "ERROR" << std::endl; + } + assert(bytesRead <= bufferedBytes_ && "Predecode consumed more bytes than were available"); // Increment the offset, decrement available bytes + std::cerr << "180 bytes read: " << (int)bytesRead << std::endl; + bufferOffset += bytesRead; + + std::cerr << "bufferOffset becomes: " << (int)bufferOffset << std::endl; + bufferedBytes_ -= bytesRead; + std::cerr << "179: " << (int)bufferedBytes_ << std::endl; if (!prediction.taken) { // Predicted as not taken; increment PC to next instruction pc_ += bytesRead; + std::cerr << "+bytes read" << std::endl; + } else { // Predicted as taken; set PC to predicted target address pc_ = prediction.target; + std::cerr << "predict target = " << std::hex << prediction.target + << std::dec << std::endl; } if (pc_ >= programByteLength_) { @@ -216,6 +242,8 @@ void FetchUnit::registerLoopBoundary(uint64_t branchAddress) { bool FetchUnit::hasHalted() const { return hasHalted_; } void FetchUnit::updatePC(uint64_t address) { + std::cerr << "238 pc_ = " << address << std::endl; + pc_ = address; bufferedBytes_ = 0; hasHalted_ = (pc_ >= programByteLength_); @@ -240,6 +268,8 @@ void FetchUnit::requestFromPC() { } else { // Fetch buffer is empty, so fetch from the PC blockAddress = pc_ & blockMask_; + std::cerr << "264 block address " << std::hex << blockAddress << std::dec + << std::endl; } instructionMemory_.requestRead({blockAddress, blockSize_}); diff --git a/src/tools/simeng/main.cc b/src/tools/simeng/main.cc index 9e6bd05eef..16d5b2cf42 100644 --- a/src/tools/simeng/main.cc +++ b/src/tools/simeng/main.cc @@ -17,6 +17,8 @@ uint64_t simulate(simeng::Core& core, simeng::MemoryInterface& dataMemory, // Tick the core and memory interfaces until the program has halted while (!core.hasHalted() || dataMemory.hasPendingRequests()) { + std::cerr << "tick" << std::endl; + // Tick the core core.tick(); From f990a466508123b76de08bbe1f8f81a971d5dc5b Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 9 Jan 2024 11:08:09 +0000 Subject: [PATCH 048/115] Fix OoO core --- src/lib/arch/riscv/Architecture.cc | 18 +++++++----------- src/lib/arch/riscv/InstructionMetadata.cc | 1 - src/lib/arch/riscv/Instruction_decode.cc | 3 --- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 480104891c..f689c7e4c4 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -160,9 +160,6 @@ Architecture::~Architecture() { uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { - std::cerr << "predecode at address: " << std::hex << instructionAddress - << std::dec << std::endl; - // Check that instruction address is 4-byte aligned as required by RISC-V // 2-byte when Compressed ISA is supported if (instructionAddress & constants_.alignMask) { @@ -178,8 +175,6 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, return 1; } - std::cerr << "predecode bytes avail " << (int)bytesAvailable << std::endl; - assert(bytesAvailable >= constants_.bytesLimit && "Fewer than bytes limit supplied to RISC-V decoder"); @@ -208,6 +203,12 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, auto metadata = success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding); + if (metadata.id == RISCV_INS_INVALID) { + // Invalid decoding, potentially read over the end of the valid buffer. + // BAIL. Do not add to cache as may be incorrect data + return 0; + } + // Cache the metadata metadataCache.push_front(metadata); @@ -221,7 +222,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, if (iter->second.getMetadata().lenBytes > bytesAvailable) { // Too many bytes read. BAIL - std::cerr << "TOO MANY BYTES READ" << std::endl; + // TODO don't write to cache return 0; } @@ -231,13 +232,8 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, // Retrieve the cached instruction and write to output uop = std::make_shared(iter->second); - std::cerr << "setInstructionAddress: " << std::hex << instructionAddress - << std::dec << std::endl; - uop->setInstructionAddress(instructionAddress); - std::cerr << std::hex << instructionAddress << std::dec << std::endl; - return iter->second.getMetadata().lenBytes; } diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index c043f0e243..7af63bc4a8 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -16,7 +16,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitDestinationCount(insn.detail->regs_write_count), operandCount(insn.detail->riscv.op_count) { // std::memcpy(encoding, insn.bytes, sizeof(encoding)); - std::cerr << "metadata insn size" << insn.size << std::endl; setLength(insn.size); std::memset(encoding, 0, 4); diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 5d97b81e87..8d8067e320 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -65,9 +65,6 @@ Register csRegToRegister(unsigned int reg) { *****************/ void Instruction::decode() { if (metadata.id == RISCV_INS_INVALID) { - std::cerr << "INVALID at " << std::hex << instructionAddress_ << std::dec - << std::endl; - exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; return; From 472461c4ff4b18a9c3c4681ca4fd4fdb60c9f31e Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 9 Jan 2024 13:01:05 +0000 Subject: [PATCH 049/115] Remove prints and ensure not too many bytes read --- configs/DEMO_RISCV.yaml | 2 +- src/lib/arch/riscv/Architecture.cc | 9 +++-- src/lib/arch/riscv/Instruction_execute.cc | 9 +++-- src/lib/pipeline/FetchUnit.cc | 42 +++++++++++++---------- src/tools/simeng/main.cc | 2 +- 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 42e7418b55..248d713d64 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -4,7 +4,7 @@ Core: ISA: rv64 - Simulation-Mode: outoforder + Simulation-Mode: inorderpipelined Clock-Frequency-GHz: 2.5 Timer-Frequency-MHz: 200 Fetch: diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index f689c7e4c4..81d2faedd0 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -209,6 +209,12 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, return 0; } + if (metadata.lenBytes > bytesAvailable) { + // Too many bytes read. BAIL + // TODO don't write to cache + return 0; + } + // Cache the metadata metadataCache.push_front(metadata); @@ -221,8 +227,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, } if (iter->second.getMetadata().lenBytes > bytesAvailable) { - // Too many bytes read. BAIL - // TODO don't write to cache + // If cached but too many bytes read. BAIL return 0; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index d18b5df28f..f84fa92189 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,8 +179,13 @@ void Instruction::execute() { // Implementation of rv64iamfdc according to the v. 20191213 unprivileged spec - // std::cerr << std::hex << instructionAddress_ << " " << metadata.mnemonic - // << " " << metadata.operandStr << std::dec << std::endl; + // static int n = 0; + // n++; + // + // if (n < 100) { + // std::cerr << std::hex << instructionAddress_ << " " << metadata.mnemonic + // << " " << metadata.operandStr << std::dec << std::endl; + // } executed_ = true; switch (metadata.opcode) { diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 777850516d..a42a01a843 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -61,6 +61,7 @@ void FetchUnit::tick() { uint8_t bufferOffset; // Check if more instruction data is required + // TODO should this be minimum instructions size??? if (bufferedBytes_ < isa_.getMaxInstructionSize()) { // Calculate the address of the next fetch block uint64_t blockAddress; @@ -73,8 +74,9 @@ void FetchUnit::tick() { // Fetch buffer is empty, so start from the PC blockAddress = pc_ & blockMask_; bufferOffset = pc_ - blockAddress; - std::cerr << "76 bufferOffset: " << (int)bufferOffset << " = " << (int)pc_ - << " - " << (int)blockAddress << std::endl; + // std::cerr << "76 bufferOffset: " << (int)bufferOffset << " = " << + // (int)pc_ + // << " - " << (int)blockAddress << std::endl; } // Find fetched memory that matches the desired block @@ -99,12 +101,13 @@ void FetchUnit::tick() { std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, blockSize_ - bufferOffset); - std::cerr << "pre101: " << (int)bufferedBytes_ << " += " << (int)blockSize_ - << " - " << (int)bufferOffset << std::endl; + // std::cerr << "pre101: " << (int)bufferedBytes_ << " += " << + // (int)blockSize_ + // << " - " << (int)bufferOffset << std::endl; // TODO can bufferedBytes_ go above the block size? bufferedBytes_ += blockSize_ - bufferOffset; - std::cerr << "101: " << (int)bufferedBytes_ << std::endl; + // std::cerr << "101: " << (int)bufferedBytes_ << std::endl; buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. @@ -125,14 +128,15 @@ void FetchUnit::tick() { auto bytesRead = isa_.predecode(buffer + bufferOffset, bufferedBytes_, pc_, macroOp); - std::cerr << "Bytes read = " << (int)bytesRead << std::endl; + // std::cerr << "Bytes read = " << (int)bytesRead << std::endl; // If predecode fails, bail and wait for more data if (bytesRead == 0) { - std::cerr << "BAIL" << std::endl; + // std::cerr << "BAIL" << std::endl; - assert(bufferedBytes_ < isa_.getMaxInstructionSize() && - "unexpected predecode failure"); + // TODO should be minimum?? + // assert(bufferedBytes_ < isa_.getMaxInstructionSize() && + // "unexpected predecode failure"); break; } @@ -182,25 +186,26 @@ void FetchUnit::tick() { assert(bytesRead <= bufferedBytes_ && "Predecode consumed more bytes than were available"); // Increment the offset, decrement available bytes - std::cerr << "180 bytes read: " << (int)bytesRead << std::endl; + // std::cerr << "180 bytes read: " << (int)bytesRead << std::endl; bufferOffset += bytesRead; - std::cerr << "bufferOffset becomes: " << (int)bufferOffset << std::endl; + // std::cerr << "bufferOffset becomes: " << (int)bufferOffset << + // std::endl; bufferedBytes_ -= bytesRead; - std::cerr << "179: " << (int)bufferedBytes_ << std::endl; + // std::cerr << "179: " << (int)bufferedBytes_ << std::endl; if (!prediction.taken) { // Predicted as not taken; increment PC to next instruction pc_ += bytesRead; - std::cerr << "+bytes read" << std::endl; + // std::cerr << "+bytes read" << std::endl; } else { // Predicted as taken; set PC to predicted target address pc_ = prediction.target; - std::cerr << "predict target = " << std::hex << prediction.target - << std::dec << std::endl; + // std::cerr << "predict target = " << std::hex << prediction.target + // << std::dec << std::endl; } if (pc_ >= programByteLength_) { @@ -242,7 +247,7 @@ void FetchUnit::registerLoopBoundary(uint64_t branchAddress) { bool FetchUnit::hasHalted() const { return hasHalted_; } void FetchUnit::updatePC(uint64_t address) { - std::cerr << "238 pc_ = " << address << std::endl; + // std::cerr << "238 pc_ = " << address << std::endl; pc_ = address; bufferedBytes_ = 0; @@ -268,8 +273,9 @@ void FetchUnit::requestFromPC() { } else { // Fetch buffer is empty, so fetch from the PC blockAddress = pc_ & blockMask_; - std::cerr << "264 block address " << std::hex << blockAddress << std::dec - << std::endl; + // std::cerr << "264 block address " << std::hex << blockAddress << + // std::dec + // << std::endl; } instructionMemory_.requestRead({blockAddress, blockSize_}); diff --git a/src/tools/simeng/main.cc b/src/tools/simeng/main.cc index 16d5b2cf42..9c8aa71214 100644 --- a/src/tools/simeng/main.cc +++ b/src/tools/simeng/main.cc @@ -17,7 +17,7 @@ uint64_t simulate(simeng::Core& core, simeng::MemoryInterface& dataMemory, // Tick the core and memory interfaces until the program has halted while (!core.hasHalted() || dataMemory.hasPendingRequests()) { - std::cerr << "tick" << std::endl; + // std::cerr << "tick" << std::endl; // Tick the core core.tick(); From f0489d87f4565b1d023cbcaedad54497ce9ac629 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 10 Jan 2024 16:44:20 +0000 Subject: [PATCH 050/115] Cleanup ready for PR --- configs/DEMO_RISCV.yaml | 2 +- src/include/simeng/arch/riscv/Instruction.hh | 3 +- src/lib/arch/riscv/Architecture.cc | 19 +++++----- src/lib/arch/riscv/Instruction_decode.cc | 1 - src/lib/arch/riscv/Instruction_execute.cc | 17 --------- src/lib/pipeline/FetchUnit.cc | 38 +++----------------- src/tools/simeng/main.cc | 2 -- 7 files changed, 15 insertions(+), 67 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 248d713d64..42e7418b55 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -4,7 +4,7 @@ Core: ISA: rv64 - Simulation-Mode: inorderpipelined + Simulation-Mode: outoforder Clock-Frequency-GHz: 2.5 Timer-Frequency-MHz: 200 Fetch: diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index a8cd1a7787..c506b7337c 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -180,7 +180,6 @@ class Instruction : public simeng::Instruction { * instruction can have. */ static const uint8_t MAX_DESTINATION_REGISTERS = 1; - private: /** A reference to the ISA instance this instruction belongs to. */ const Architecture& architecture_; @@ -201,7 +200,7 @@ class Instruction : public simeng::Instruction { * `sourceRegisters` entry. */ // TODO this name change requires updates of the docs on approval // developer/arch/supported/aarch64.html#aarch64-adding-execution-behaviour-operands - // TODO update AArch64 to keep both inline and references in docs from RISC-V + // TODO update AArch64 to keep both in line and references in docs from RISC-V // to AArch64 correct std::array sourceRegValues; diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 81d2faedd0..344ef8c0e7 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -20,11 +20,11 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) // TODO set fcsr accordingly when Zicsr extension supported fesetround(FE_TONEAREST); - cs_mode csMode = CS_MODE_RISCV64; constantsPool constantsPool; - // TODO if here to check if compressed instructions are allowed based off of - // config options + // TODO an 'if' clause could be added here to check if compressed instructions + // are allowed based off of config options which selects the corrct cs_mode + // and constants. Currently always rv64gc allowed constants_.alignMask = constantsPool.alignMaskCompressed; constants_.regWidth = constantsPool.byteLength64; @@ -178,8 +178,6 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, assert(bytesAvailable >= constants_.bytesLimit && "Fewer than bytes limit supplied to RISC-V decoder"); - // TODO should this still be 4 bytes?? Seems to work as is - // Dereference the instruction pointer to obtain the instruction word uint32_t insn; memcpy(&insn, ptr, 4); @@ -200,21 +198,20 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, bool success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); - auto metadata = - success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding); - - if (metadata.id == RISCV_INS_INVALID) { + if (!success || rawInsn.opcode == RISCV_INS_INVALID) { // Invalid decoding, potentially read over the end of the valid buffer. // BAIL. Do not add to cache as may be incorrect data return 0; } - if (metadata.lenBytes > bytesAvailable) { + if (rawInsn.size > bytesAvailable) { // Too many bytes read. BAIL - // TODO don't write to cache return 0; } + auto metadata = + success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding); + // Cache the metadata metadataCache.push_front(metadata); diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 8d8067e320..b9e7867fbf 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -202,7 +202,6 @@ void Instruction::decode() { // First operand is never MEM type, only check after the first. If register // contains memory address, extract reg number from capstone object - // TODO also extract offset for instruction address? else if (i > 0 && op.type == RISCV_OP_MEM) { // Memory operand sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index f84fa92189..47d29d0a8d 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,14 +179,6 @@ void Instruction::execute() { // Implementation of rv64iamfdc according to the v. 20191213 unprivileged spec - // static int n = 0; - // n++; - // - // if (n < 100) { - // std::cerr << std::hex << instructionAddress_ << " " << metadata.mnemonic - // << " " << metadata.operandStr << std::dec << std::endl; - // } - executed_ = true; switch (metadata.opcode) { case Opcode::RISCV_LB: { // LB rd,rs1,imm @@ -1690,15 +1682,6 @@ void Instruction::execute() { default: return executionNYI(); } - // std::cerr << "0x" << std::hex << instructionAddress_ << std::dec << ": " - // << metadata.mnemonic << " " << metadata.operandStr; - // if (results[0]) { - // uint64_t val = results[0].get(); - // - // std::cerr << " => " << val << std::endl; - // } else { - // std::cerr << std::endl; - // } } } // namespace riscv diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index a42a01a843..426d19cfb8 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -61,7 +61,7 @@ void FetchUnit::tick() { uint8_t bufferOffset; // Check if more instruction data is required - // TODO should this be minimum instructions size??? + // TODO Unsure of whether this should be minimum instruction size instead if (bufferedBytes_ < isa_.getMaxInstructionSize()) { // Calculate the address of the next fetch block uint64_t blockAddress; @@ -74,9 +74,6 @@ void FetchUnit::tick() { // Fetch buffer is empty, so start from the PC blockAddress = pc_ & blockMask_; bufferOffset = pc_ - blockAddress; - // std::cerr << "76 bufferOffset: " << (int)bufferOffset << " = " << - // (int)pc_ - // << " - " << (int)blockAddress << std::endl; } // Find fetched memory that matches the desired block @@ -101,13 +98,8 @@ void FetchUnit::tick() { std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, blockSize_ - bufferOffset); - // std::cerr << "pre101: " << (int)bufferedBytes_ << " += " << - // (int)blockSize_ - // << " - " << (int)bufferOffset << std::endl; - // TODO can bufferedBytes_ go above the block size? bufferedBytes_ += blockSize_ - bufferOffset; - // std::cerr << "101: " << (int)bufferedBytes_ << std::endl; buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. @@ -128,13 +120,12 @@ void FetchUnit::tick() { auto bytesRead = isa_.predecode(buffer + bufferOffset, bufferedBytes_, pc_, macroOp); - // std::cerr << "Bytes read = " << (int)bytesRead << std::endl; - // If predecode fails, bail and wait for more data if (bytesRead == 0) { - // std::cerr << "BAIL" << std::endl; - - // TODO should be minimum?? + // TODO should be minimum? + // Assertion currently commented as bytesRead == 0 is used to force + // finishing tick on compressed instruction edge cases which are correct + // behaviour // assert(bufferedBytes_ < isa_.getMaxInstructionSize() && // "unexpected predecode failure"); break; @@ -179,33 +170,19 @@ void FetchUnit::tick() { loopBufferState_ = LoopBufferState::FILLING; } - if (bytesRead > bufferedBytes_) { - std::cerr << "ERROR" << std::endl; - } - assert(bytesRead <= bufferedBytes_ && "Predecode consumed more bytes than were available"); // Increment the offset, decrement available bytes - // std::cerr << "180 bytes read: " << (int)bytesRead << std::endl; bufferOffset += bytesRead; - // std::cerr << "bufferOffset becomes: " << (int)bufferOffset << - // std::endl; - bufferedBytes_ -= bytesRead; - // std::cerr << "179: " << (int)bufferedBytes_ << std::endl; - if (!prediction.taken) { // Predicted as not taken; increment PC to next instruction pc_ += bytesRead; - // std::cerr << "+bytes read" << std::endl; - } else { // Predicted as taken; set PC to predicted target address pc_ = prediction.target; - // std::cerr << "predict target = " << std::hex << prediction.target - // << std::dec << std::endl; } if (pc_ >= programByteLength_) { @@ -247,8 +224,6 @@ void FetchUnit::registerLoopBoundary(uint64_t branchAddress) { bool FetchUnit::hasHalted() const { return hasHalted_; } void FetchUnit::updatePC(uint64_t address) { - // std::cerr << "238 pc_ = " << address << std::endl; - pc_ = address; bufferedBytes_ = 0; hasHalted_ = (pc_ >= programByteLength_); @@ -273,9 +248,6 @@ void FetchUnit::requestFromPC() { } else { // Fetch buffer is empty, so fetch from the PC blockAddress = pc_ & blockMask_; - // std::cerr << "264 block address " << std::hex << blockAddress << - // std::dec - // << std::endl; } instructionMemory_.requestRead({blockAddress, blockSize_}); diff --git a/src/tools/simeng/main.cc b/src/tools/simeng/main.cc index 9c8aa71214..9e6bd05eef 100644 --- a/src/tools/simeng/main.cc +++ b/src/tools/simeng/main.cc @@ -17,8 +17,6 @@ uint64_t simulate(simeng::Core& core, simeng::MemoryInterface& dataMemory, // Tick the core and memory interfaces until the program has halted while (!core.hasHalted() || dataMemory.hasPendingRequests()) { - // std::cerr << "tick" << std::endl; - // Tick the core core.tick(); From 7d529830d1e2fd8c7e900340db6073b3372a2faf Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 19 Jan 2024 12:31:54 +0000 Subject: [PATCH 051/115] Update sourceRegValues name and apply to AArch64 --- .../simeng/arch/aarch64/Instruction.hh | 2 +- src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/aarch64/Instruction.cc | 6 +- src/lib/arch/aarch64/Instruction_address.cc | 517 +++-- src/lib/arch/aarch64/Instruction_decode.cc | 4 +- src/lib/arch/aarch64/Instruction_execute.cc | 1995 +++++++++-------- src/lib/arch/riscv/Instruction.cc | 7 +- src/lib/arch/riscv/Instruction_address.cc | 18 +- src/lib/arch/riscv/Instruction_decode.cc | 4 +- src/lib/arch/riscv/Instruction_execute.cc | 410 ++-- 10 files changed, 1520 insertions(+), 1445 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index d61bb43582..1203a119fc 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -390,7 +390,7 @@ class Instruction : public simeng::Instruction { /** A vector of provided operand values. Each entry corresponds to a * `sourceRegisters` entry. */ - std::vector operands; + std::vector srcRegVals; /** A vector of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index c506b7337c..3c34e71ba4 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -202,7 +202,7 @@ class Instruction : public simeng::Instruction { // developer/arch/supported/aarch64.html#aarch64-adding-execution-behaviour-operands // TODO update AArch64 to keep both in line and references in docs from RISC-V // to AArch64 correct - std::array sourceRegValues; + std::array srcRegVals; /** Extracted value of current immediate from metadata */ int64_t imm = 0; diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index a3e0e698ad..096216e686 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -41,7 +41,7 @@ const span Instruction::getSourceRegisters() const { } const span Instruction::getSourceOperands() const { - return {const_cast(operands.data()), operands.size()}; + return {const_cast(srcRegVals.data()), srcRegVals.size()}; } const span Instruction::getDestinationRegisters() const { @@ -49,7 +49,7 @@ const span Instruction::getDestinationRegisters() const { destinationRegisterCount}; } bool Instruction::isOperandReady(int index) const { - return static_cast(operands[index]); + return static_cast(srcRegVals[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { @@ -65,7 +65,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { assert(value.size() > 0 && "Attempted to provide an uninitialised RegisterValue"); - operands[i] = value; + srcRegVals[i] = value; operandsPending--; } diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index 3878d80648..e94d7f4a7a 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -52,7 +52,7 @@ span Instruction::generateAddresses() { case MicroOpcode::LDR_ADDR: { std::vector addresses; generateContiguousAddresses( - operands[0].get() + metadata.operands[1].mem.disp, 1, + srcRegVals[0].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); @@ -61,7 +61,7 @@ span Instruction::generateAddresses() { case MicroOpcode::STR_ADDR: { std::vector addresses; generateContiguousAddresses( - operands[0].get() + metadata.operands[0].mem.disp, 1, + srcRegVals[0].get() + metadata.operands[0].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); @@ -82,11 +82,11 @@ span Instruction::generateAddresses() { : architecture_.getVectorLength(); switch (metadata.opcode) { case Opcode::AArch64_CASALW: { // casal ws, wt, [xn|sp] - setMemoryAddresses({{operands[2].get(), 4}}); + setMemoryAddresses({{srcRegVals[2].get(), 4}}); break; } case Opcode::AArch64_CASALX: { // casal xs, xt, [xn|sp] - setMemoryAddresses({{operands[2].get(), 8}}); + setMemoryAddresses({{srcRegVals[2].get(), 8}}); break; } case Opcode::AArch64_LD1_MXIPXX_V_D: // ld1d {zatv.d[ws, #imm]}, pg/z, @@ -95,10 +95,10 @@ span Instruction::generateAddresses() { // [{, xm, lsl #3}] // SME const uint16_t partition_num = VL_bits / 64; - const uint64_t n = operands[partition_num + 2].get(); + const uint64_t n = srcRegVals[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = operands[partition_num + 3].get() << 3; + m = srcRegVals[partition_num + 3].get() << 3; setMemoryAddresses({(n + m), static_cast(VL_bits / 8)}); break; } @@ -108,31 +108,31 @@ span Instruction::generateAddresses() { // [{, xm, LSL #2}] // SME const uint16_t partition_num = VL_bits / 32; - const uint64_t n = operands[partition_num + 2].get(); + const uint64_t n = srcRegVals[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = operands[partition_num + 3].get() << 2; + m = srcRegVals[partition_num + 3].get() << 2; setMemoryAddresses({(n + m), static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1i32: { // ld1 {vt.s}[index], [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_LD1i64: { // ld1 {vt.d}[index], [xn] - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } case Opcode::AArch64_LD1i64_POST: { // ld1 {vt.d}[index], [xn], #8 - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { setMemoryAddresses( - {{operands[1].get() + metadata.operands[2].mem.disp, + {{srcRegVals[1].get() + metadata.operands[2].mem.disp, 8}}); break; } @@ -141,28 +141,28 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD1RQ_D_IMM: { // ld1rqd {zd.d}, pg/z, [xn{, #imm}] uint64_t addr = - operands[1].get() + metadata.operands[2].mem.disp; + srcRegVals[1].get() + metadata.operands[2].mem.disp; setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RQ_W: { // ld1rqw {zd.s}, pg/z, [xn, xm, lsl #2] uint64_t addr = - operands[1].get() + (operands[2].get() * 4); + srcRegVals[1].get() + (srcRegVals[2].get() * 4); setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RQ_W_IMM: { // ld1rqw {zd.s}, pg/z, [xn{, #imm}] uint64_t addr = - operands[1].get() + metadata.operands[2].mem.disp; + srcRegVals[1].get() + metadata.operands[2].mem.disp; setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RW_IMM: { // ld1rw {zt.s}, pg/z, [xn, #imm] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { setMemoryAddresses( - {{operands[1].get() + metadata.operands[2].mem.disp, + {{srcRegVals[1].get() + metadata.operands[2].mem.disp, 4}}); break; } @@ -170,75 +170,75 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1Rv16b: { // ld1r {vt.16b}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv16b_POST: { // ld1r {vt.16b}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv1d: { // ld1r {vt.1d}, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv1d_POST: { // ld1r {vt.1d}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv2d: { // ld1r {vt.2d}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2d_POST: { // ld1r {vt.2d}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2s: { // ld1r {vt.2s}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2s_POST: { // ld1r {vt.2s}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv4h: { // ld1r {vt.4h}, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv4h_POST: { // ld1r {vt.4h}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8b: { // ld1r {vt.8b}, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8b_POST: { // ld1r {vt.8b}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8h: { // ld1r {vt.8h}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv8h_POST: { // ld1r {vt.8h}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv4s: { // ld1r {vt.4s}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv4s_POST: { // ld1r {vt.4s}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Onev16b: { // ld1 {vt.16b}, [xn] - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Onev16b_POST: { // ld1 {vt.16b}, [xn], #imm - setMemoryAddresses({{operands[0].get(), 16}}); + setMemoryAddresses({{srcRegVals[0].get(), 16}}); break; } case Opcode::AArch64_LD1Fourv16b: // ld1 {vt1.16b, vt2.16b, vt3.16b, @@ -258,7 +258,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_LD1Fourv4s_POST: { // ld1 {vt1.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> - uint64_t base = operands[0].get(); + uint64_t base = srcRegVals[0].get(); setMemoryAddresses( {{base, 16}, {base + 16, 16}, {base + 32, 16}, {base + 48, 16}}); break; @@ -277,20 +277,20 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_LD1Twov4s_POST: { // ld1 {vt1.4s, vt2.4s}, [xn], // <#imm|xm> - uint64_t base = operands[0].get(); + uint64_t base = srcRegVals[0].get(); setMemoryAddresses({{base, 16}, {base + 16, 16}}); break; } case Opcode::AArch64_LD1B: { // ld1b {zt.b}, pg/z, [xn, xm] - const uint64_t base = operands[1].get(); - const uint64_t offset = operands[2].get(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t offset = srcRegVals[2].get(); setMemoryAddresses({base + offset, static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, // mul vl}] - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); uint64_t addr = base + (offset * (VL_bits / 8)); @@ -299,8 +299,8 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1D: { // ld1d {zt.d}, pg/z, [xn, xm, lsl #3] - const uint64_t base = operands[1].get(); - const uint64_t offset = operands[2].get(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t offset = srcRegVals[2].get(); const uint64_t addr = base + (offset * 8); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); @@ -310,7 +310,7 @@ span Instruction::generateAddresses() { // mul vl}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const uint64_t offset = static_cast(metadata.operands[2].mem.disp); const uint64_t addr = base + (offset * partition_num * 8); @@ -319,16 +319,16 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1H: { // ld1h {zt.h}, pg/z, [xn, xm, lsl #1] - const uint64_t base = operands[1].get(); - const uint64_t offset = operands[2].get(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t offset = srcRegVals[2].get(); const uint64_t addr = base + (offset * 2); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] - const uint64_t base = operands[1].get(); - const uint64_t offset = operands[2].get(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t offset = srcRegVals[2].get(); const uint64_t addr = base + (offset * 4); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); @@ -338,7 +338,7 @@ span Instruction::generateAddresses() { // mul vl}] const uint16_t partition_num = VL_bits / 32; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); const uint64_t addr = base + (offset * partition_num * 4); @@ -348,8 +348,8 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD2D: { // ld2d {zt1.d, zt2.d}, pg/z, [xn|sp, xm, // lsl #3] - const uint64_t base = operands[1].get(); - uint64_t offset = operands[2].get(); + const uint64_t base = srcRegVals[1].get(); + uint64_t offset = srcRegVals[2].get(); std::vector addresses; addresses.reserve(2); @@ -366,7 +366,7 @@ span Instruction::generateAddresses() { // [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[3].mem.disp); std::vector addresses; @@ -385,7 +385,7 @@ span Instruction::generateAddresses() { // [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[4].mem.disp); std::vector addresses; @@ -405,7 +405,7 @@ span Instruction::generateAddresses() { // pg/z, [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[5].mem.disp); std::vector addresses; @@ -427,74 +427,76 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD2Twov4s_POST: { // ld2 {vt1.4s, vt2.4s}, [xn], // #imm - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); setMemoryAddresses({{base, 16}, {base + 16, 16}}); break; } case Opcode::AArch64_LDADDLW: // ldaddl ws, wt, [xn] [[fallthrough]]; case Opcode::AArch64_LDADDW: { // ldadd ws, wt, [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_LDARB: { // ldarb wt, [xn] - setMemoryAddresses({{operands[0].get(), 1}}); + setMemoryAddresses({{srcRegVals[0].get(), 1}}); break; } case Opcode::AArch64_LDARW: { // ldar wt, [xn] - setMemoryAddresses({{operands[0].get(), 4}}); + setMemoryAddresses({{srcRegVals[0].get(), 4}}); break; } case Opcode::AArch64_LDARX: { // ldar xt, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LDAXRW: { // ldaxr wd, [xn] - setMemoryAddresses({{operands[0].get(), 4}}); + setMemoryAddresses({{srcRegVals[0].get(), 4}}); break; } case Opcode::AArch64_LDAXRX: { // ldaxr xd, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_LDRBBpost: { // ldrb wt, [xn], #imm - setMemoryAddresses({{operands[0].get(), 1}}); + setMemoryAddresses({{srcRegVals[0].get(), 1}}); break; } case Opcode::AArch64_LDRBBpre: { // ldrb wt, [xn, #imm]! setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_LDRBBroW: { // ldrb wt, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 1}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRBBroX: { // ldrb wt, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 1}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRBBui: { // ldrb wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_LDRDroW: { // ldr dt, [xn, wm{, extend {amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 8}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRDroX: { // ldr dt, [xn, xm{, extend {amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 8}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRBui: // ldr bt, [xn, #imm] @@ -513,7 +515,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDRXpre: { // ldr xt, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - operands[0].get() + metadata.operands[1].mem.disp, 1, + srcRegVals[0].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -526,53 +528,55 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDRWpost: // ldr wt, [xn], #imm case Opcode::AArch64_LDRXpost: { // ldr xt, [xn], #imm std::vector addresses; - generateContiguousAddresses(operands[0].get(), 1, dataSize_, + generateContiguousAddresses(srcRegVals[0].get(), 1, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_LDRHHpost: { // ldrh wt, [xn], #imm - setMemoryAddresses({{operands[0].get(), 2}}); + setMemoryAddresses({{srcRegVals[0].get(), 2}}); break; } case Opcode::AArch64_LDRHHpre: { // ldrh wt, [xn, #imm]! setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_LDRHHroW: { // ldrh wt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRHHroX: { // ldrh wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRHHui: { // ldrh wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_LDRQroX: { // ldr qt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 16}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 16}}); break; } case Opcode::AArch64_LDRSroW: { // ldr st, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 4}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSroX: { // ldr st, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 4}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSWl: { // ldrsw xt, #imm @@ -582,14 +586,14 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDRWroW: { // ldr wt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 4}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRWroX: { // ldr wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 4}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRXl: { // ldr xt, #imm @@ -599,21 +603,21 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDRXroW: { // ldr xt, [xn, wn{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 8}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRXroX: { // ldr xt, [xn, xn{, extend {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 8}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDR_PXI: { // ldr pt, [xn{, #imm, mul vl}] const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint64_t base = operands[0].get(); + const uint64_t base = srcRegVals[0].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -625,7 +629,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDR_ZXI: { // ldr zt, [xn{, #imm, mul vl}] const uint16_t partition_num = VL_bits / 8; - const uint64_t base = operands[0].get(); + const uint64_t base = srcRegVals[0].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); const uint64_t addr = base + (offset * partition_num); @@ -635,7 +639,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDNPSi: { // ldnp st1, st2, [xn, #imm] uint64_t base = - operands[0].get() + metadata.operands[2].mem.disp; + srcRegVals[0].get() + metadata.operands[2].mem.disp; setMemoryAddresses({{base, 4}, {base + 4, 4}}); break; } @@ -651,7 +655,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDPXpre: { // ldp xt1, xt2, [xn, #imm!] std::vector addresses; generateContiguousAddresses( - operands[0].get() + metadata.operands[2].mem.disp, 2, + srcRegVals[0].get() + metadata.operands[2].mem.disp, 2, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -662,136 +666,147 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDPWpost: // ldp wt1, wt2, [xn], #imm case Opcode::AArch64_LDPXpost: { // ldp xt1, xt2, [xn], #imm std::vector addresses; - generateContiguousAddresses(operands[0].get(), 2, dataSize_, + generateContiguousAddresses(srcRegVals[0].get(), 2, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_LDPSWi: { // ldpsw xt1, xt2, [xn {, #imm}] uint64_t base = - operands[0].get() + metadata.operands[2].mem.disp; + srcRegVals[0].get() + metadata.operands[2].mem.disp; setMemoryAddresses({{base, 4}, {base + 4, 4}}); break; } case Opcode::AArch64_LDRSBWroX: { // ldrsb wt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 1}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRSBWui: { // ldrsb xt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_LDRSBXui: { // ldrsb xt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_LDRSHWroW: { // ldrsh wt, [xn, wm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHWroX: { // ldrsh wt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHWui: { // ldrsh wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_LDRSHXroW: { // ldrsh xt, [xn, wm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHXroX: { // ldrsh xt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 2}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHXui: { // ldrsh xt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_LDRSWpost: { // ldrsw xt, [xn], #simm - setMemoryAddresses({{operands[0].get(), 4}}); + setMemoryAddresses({{srcRegVals[0].get(), 4}}); break; } case Opcode::AArch64_LDRSWroX: { // ldrsw xt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(operands[1].get(), metadata.operands[1]); - setMemoryAddresses({{operands[0].get() + offset, 4}}); + extendOffset(srcRegVals[1].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSWui: { // ldrsw xt, [xn{, #pimm}] uint64_t base = - operands[0].get() + metadata.operands[1].mem.disp; + srcRegVals[0].get() + metadata.operands[1].mem.disp; setMemoryAddresses({{base, 4}}); break; } case Opcode::AArch64_LDURBBi: { // ldurb wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_LDURDi: { // ldur dt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 8}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 8}}); break; } case Opcode::AArch64_LDURHHi: { // ldurh wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_LDURQi: { // ldur qt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, 16}}); break; } case Opcode::AArch64_LDURSWi: { // ldursw xt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 4}}); break; } case Opcode::AArch64_LDURSi: { // ldur sd, [{, #imm}] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 4}}); break; } case Opcode::AArch64_LDURWi: { // ldur wt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 4}}); break; } case Opcode::AArch64_LDURXi: { // ldur xt, [xn, #imm] setMemoryAddresses( - {{operands[0].get() + metadata.operands[1].mem.disp, 8}}); + {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + 8}}); break; } case Opcode::AArch64_LDXRW: { // ldxr wt, [xn] - setMemoryAddresses({{operands[0].get(), 4}}); + setMemoryAddresses({{srcRegVals[0].get(), 4}}); break; } case Opcode::AArch64_LDXRX: { // ldxr xt, [xn] - setMemoryAddresses({{operands[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::AArch64_PRFMui: { // prfm op, [xn, xm{, extend {#amount}}] @@ -799,11 +814,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1B: { // st1b {zt.b}, pg, [xn, xm] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 8; - const uint64_t base = operands[2].get(); - const uint64_t offset = operands[3].get(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t offset = srcRegVals[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -814,10 +829,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1B_IMM: { // st1b {zt.b}, pg, [xn{, #imm, mul vl}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 8; - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -831,11 +846,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); - const uint64_t* offset = operands[3].getAsVector(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t* offset = srcRegVals[3].getAsVector(); std::vector addresses; @@ -850,11 +865,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); - const uint64_t* offset = operands[3].getAsVector(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t* offset = srcRegVals[3].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -871,11 +886,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { // st1d {zt.d}, pg, [xn, // zm.d, lsl #3] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); - const uint64_t* offset = operands[3].getAsVector(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t* offset = srcRegVals[3].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -891,11 +906,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1D: { // st1d {zt.d}, pg, [xn, xm, lsl #3] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); - const uint64_t offset = operands[3].get(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t offset = srcRegVals[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -906,10 +921,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1D_IMM: { // st1d {zt.d}, pg, [xn{, #imm, mul vl}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -924,10 +939,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST2D_IMM: { // st2d {zt1.d, zt2.d}, pg, [{, // #imm, mul vl}] - const uint64_t* p = operands[2].getAsVector(); + const uint64_t* p = srcRegVals[2].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[3].get(); + const uint64_t base = srcRegVals[3].get(); const int64_t offset = static_cast(metadata.operands[3].mem.disp); @@ -948,11 +963,11 @@ span Instruction::generateAddresses() { // SME const uint16_t partition_num = VL_bits / 64; const uint64_t* pg = - operands[partition_num + 1].getAsVector(); - const uint64_t n = operands[partition_num + 2].get(); + srcRegVals[partition_num + 1].getAsVector(); + const uint64_t n = srcRegVals[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = operands[partition_num + 3].get() << 3; + m = srcRegVals[partition_num + 3].get() << 3; std::vector addresses; addresses.reserve(partition_num); @@ -969,11 +984,11 @@ span Instruction::generateAddresses() { // SME const uint16_t partition_num = VL_bits / 32; const uint64_t* pg = - operands[partition_num + 1].getAsVector(); - const uint64_t n = operands[partition_num + 2].get(); + srcRegVals[partition_num + 1].getAsVector(); + const uint64_t n = srcRegVals[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = operands[partition_num + 3].get() << 2; + m = srcRegVals[partition_num + 3].get() << 2; std::vector addresses; addresses.reserve(partition_num); @@ -984,11 +999,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1W: { // st1w {zt.s}, pg, [xn, xm, lsl #2] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t base = operands[2].get(); - const uint64_t offset = operands[3].get(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t offset = srcRegVals[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -999,11 +1014,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1W_D: { // st1w {zt.d}, pg, [xn, xm, lsl #2] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[2].get(); - const uint64_t offset = operands[3].get(); + const uint64_t base = srcRegVals[2].get(); + const uint64_t offset = srcRegVals[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -1015,10 +1030,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST1W_IMM: { // st1w {zt.s}, pg, [xn{, #imm, mul // vl}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1032,10 +1047,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1W_D_IMM: { // st1w {zt.d}, pg, [zn.d{, #imm}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = operands[2].getAsVector(); + const uint64_t* n = srcRegVals[2].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1053,10 +1068,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1W_IMM: { // st1w {zt.s}, pg, [zn.s{, #imm}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint32_t* n = operands[2].getAsVector(); + const uint32_t* n = srcRegVals[2].getAsVector(); const int64_t offset = static_cast( static_cast(metadata.operands[2].mem.disp)); @@ -1074,11 +1089,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_GLD1D_REAL: { // ld1d {zt.d}, pg/z, [xn, zm.d] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); - const uint64_t* offset = operands[2].getAsVector(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t* offset = srcRegVals[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1095,11 +1110,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, // zm.d, LSL #3] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = operands[1].get(); - const uint64_t* offset = operands[2].getAsVector(); + const uint64_t base = srcRegVals[1].get(); + const uint64_t* offset = srcRegVals[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1116,10 +1131,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, // #imm}] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = operands[1].getAsVector(); + const uint64_t* n = srcRegVals[1].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1138,10 +1153,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, // [zn.d{, #imm}] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = operands[1].getAsVector(); + const uint64_t* n = srcRegVals[1].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1160,11 +1175,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, // [, zm.d, lsl #2] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t n = operands[1].get(); - const uint64_t* m = operands[2].getAsVector(); + const uint64_t n = srcRegVals[1].get(); + const uint64_t* m = srcRegVals[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1181,11 +1196,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, // [, zm.s, sxtw] - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t n = operands[1].get(); - const uint32_t* m = operands[2].getAsVector(); + const uint64_t n = srcRegVals[1].get(); + const uint32_t* m = srcRegVals[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1201,10 +1216,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1D_IMM: { // st1d {zt.d}, pg, [zn.d{, #imm}] - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = operands[2].getAsVector(); + const uint64_t* n = srcRegVals[2].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1223,7 +1238,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST1Fourv2s_POST: { // st1 {vt.2s, vt2.2s, vt3.2s, // vt4.2s}, [xn], <#imm|xm> - const uint64_t base = operands[4].get(); + const uint64_t base = srcRegVals[4].get(); std::vector addresses; addresses.reserve(4); @@ -1250,7 +1265,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_ST1Fourv4s_POST: { // st1 {vt.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> - const uint64_t base = operands[4].get(); + const uint64_t base = srcRegVals[4].get(); std::vector addresses; addresses.reserve(4); @@ -1274,7 +1289,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_ST1Twov4s_POST: { // st1 {vt.4s, vt2.4s}, [xn], // <#imm|xm> - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); std::vector addresses; addresses.reserve(2); @@ -1287,30 +1302,30 @@ span Instruction::generateAddresses() { case Opcode::AArch64_ST1i8_POST: [[fallthrough]]; case Opcode::AArch64_ST1i8: { // st1 {vt.b}[index], [xn] - setMemoryAddresses({{operands[1].get(), 1}}); + setMemoryAddresses({{srcRegVals[1].get(), 1}}); break; } case Opcode::AArch64_ST1i16_POST: [[fallthrough]]; case Opcode::AArch64_ST1i16: { // st1 {vt.h}[index], [xn] - setMemoryAddresses({{operands[1].get(), 2}}); + setMemoryAddresses({{srcRegVals[1].get(), 2}}); break; } case Opcode::AArch64_ST1i32_POST: [[fallthrough]]; case Opcode::AArch64_ST1i32: { // st1 {vt.s}[index], [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_ST1i64_POST: [[fallthrough]]; case Opcode::AArch64_ST1i64: { // st1 {vt.d}[index], [xn] - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } case Opcode::AArch64_ST2Twov4s_POST: { // st2 {vt1.4s, vt2.4s}, [xn], // #imm - const uint64_t base = operands[2].get(); + const uint64_t base = srcRegVals[2].get(); std::vector addresses; addresses.reserve(2); @@ -1322,23 +1337,23 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_STLRB: { // stlrb wt, [xn] - setMemoryAddresses({{operands[1].get(), 1}}); + setMemoryAddresses({{srcRegVals[1].get(), 1}}); break; } case Opcode::AArch64_STLRW: { // stlr wt, [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_STLRX: { // stlr xt, [xn] - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } case Opcode::AArch64_STLXRW: { // stlxr ws, wt, [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_STLXRX: { // stlxr ws, xt, [xn] - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } case Opcode::AArch64_STPDi: // stp dt1, dt2, [xn, #imm] @@ -1353,7 +1368,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STPXpre: { // stp xt1, xt2, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - operands[2].get() + metadata.operands[2].mem.disp, 2, + srcRegVals[2].get() + metadata.operands[2].mem.disp, 2, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -1364,49 +1379,51 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STPWpost: // stp wt1, wt2, [xn], #imm case Opcode::AArch64_STPXpost: { // stp xt1, xt2, [xn], #imm std::vector addresses; - generateContiguousAddresses(operands[2].get(), 2, dataSize_, + generateContiguousAddresses(srcRegVals[2].get(), 2, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_STRBBpost: { // strb wd, [xn], #imm - setMemoryAddresses({{operands[1].get(), 1}}); + setMemoryAddresses({{srcRegVals[1].get(), 1}}); break; } case Opcode::AArch64_STRBBpre: { // strb wd, [xn, #imm]! setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_STRBBroW: { // strb wd, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 1}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 1}}); break; } case Opcode::AArch64_STRBBroX: { // strb wd, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 1}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 1}}); break; } case Opcode::AArch64_STRBBui: { // strb wd, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_STRDroW: { // str dt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 8}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRDroX: { // str dt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 8}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRBui: // str bt, [xn, #imm] @@ -1425,7 +1442,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STRXpre: { // str xt, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - operands[1].get() + metadata.operands[1].mem.disp, 1, + srcRegVals[1].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -1438,86 +1455,88 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STRWpost: // str wt, [xn], #imm case Opcode::AArch64_STRXpost: { // str xt, [xn], #imm std::vector addresses; - generateContiguousAddresses(operands[1].get(), 1, dataSize_, + generateContiguousAddresses(srcRegVals[1].get(), 1, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_STRHHpost: { // strh wt, [xn], #imm - setMemoryAddresses({{operands[1].get(), 2}}); + setMemoryAddresses({{srcRegVals[1].get(), 2}}); break; } case Opcode::AArch64_STRHHpre: { // strh wd, [xn, #imm]! setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_STRHHroW: { // strh wd, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 2}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 2}}); break; } case Opcode::AArch64_STRHHroX: { // strh wd, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 2}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 2}}); break; } case Opcode::AArch64_STRHHui: { // strh wt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_STRQroX: { // str qt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 16}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 16}}); break; } case Opcode::AArch64_STRSroW: { // str st, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 4}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRSroX: { // str st, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 4}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRWroW: { // str wd, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 4}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRWroX: { // str wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 4}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRXroW: { // str xd, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 8}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRXroX: { // str xt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(operands[2].get(), metadata.operands[1]); - setMemoryAddresses({{operands[1].get() + offset, 8}}); + extendOffset(srcRegVals[2].get(), metadata.operands[1]); + setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); break; } case Opcode::AArch64_STR_PXI: { // str pt, [xn{, #imm, mul vl}] const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -1527,7 +1546,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STR_ZXI: { // str zt, [xn{, #imm, mul vl}] const uint16_t partition_num = VL_bits / 8; - const uint64_t base = operands[1].get(); + const uint64_t base = srcRegVals[1].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -1536,46 +1555,52 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_STURBBi: { // sturb wd, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 1}}); break; } case Opcode::AArch64_STURDi: { // stur dt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 8}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 8}}); break; } case Opcode::AArch64_STURHHi: { // sturh wt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 2}}); break; } case Opcode::AArch64_STURQi: { // stur qt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, 16}}); break; } case Opcode::AArch64_STURSi: { // stur st, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 4}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 4}}); break; } case Opcode::AArch64_STURWi: { // stur wt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 4}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 4}}); break; } case Opcode::AArch64_STURXi: { // stur xt, [xn, #imm] setMemoryAddresses( - {{operands[1].get() + metadata.operands[1].mem.disp, 8}}); + {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + 8}}); break; } case Opcode::AArch64_STXRW: { // stxr ws, wt, [xn] - setMemoryAddresses({{operands[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::AArch64_STXRX: { // stxr ws, xt, [xn] - setMemoryAddresses({{operands[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } default: diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 4e60ae1b62..4cb82cdac0 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -640,12 +640,12 @@ void Instruction::decode() { // Allocate enough entries in results vector results.resize(destinationRegisterCount + 1); // Allocate enough entries in the operands vector - operands.resize(sourceRegisterCount + 1); + srcRegVals.resize(sourceRegisterCount + 1); // Catch zero register references and pre-complete those operands for (uint16_t i = 0; i < sourceRegisterCount; i++) { if (sourceRegisters[i] == Instruction::ZERO_REGISTER) { - operands[i] = RegisterValue(0, 8); + srcRegVals[i] = RegisterValue(0, 8); operandsPending--; } } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 03fe5a5410..db7b25e452 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -88,16 +88,17 @@ void Instruction::execute() { break; } case MicroOpcode::OFFSET_IMM: { - results[0] = operands[0].get() + metadata.operands[2].imm; + results[0] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case MicroOpcode::OFFSET_REG: { - results[0] = operands[0].get() + operands[1].get(); + results[0] = + srcRegVals[0].get() + srcRegVals[1].get(); break; } case MicroOpcode::STR_DATA: { setMemoryAddresses({{0, 0}}); - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } default: @@ -106,12 +107,13 @@ void Instruction::execute() { } else { switch (metadata.opcode) { case Opcode::AArch64_ADCXr: { // adc xd, xn, xm - auto [result, nzcv] = arithmeticHelp::addCarry_3ops(operands); + auto [result, nzcv] = + arithmeticHelp::addCarry_3ops(srcRegVals); results[0] = result; break; } case Opcode::AArch64_ADDPL_XXI: { // addpl xd, xn, #imm - auto x = operands[0].get(); + auto x = srcRegVals[0].get(); auto y = static_cast(metadata.operands[2].imm); // convert PL from VL_bits const uint64_t PL = VL_bits / 64; @@ -119,70 +121,70 @@ void Instruction::execute() { break; } case Opcode::AArch64_ADDPv16i8: { // addp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_ADDPv2i64: { // addp vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_ADDPv2i64p: { // addp dd, vn.2d - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_ADDPv4i32: { // addp vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_ADDPv8i16: { // addp vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_ADDSWri: { // adds wd, wn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(operands, metadata, true); + arithmeticHelp::addShift_imm(srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSWrs: { // adds wd, wn, wm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_3ops(operands, metadata, true); + arithmeticHelp::addShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSWrx: { // adds wd, wn, wm{, extend {#amount}} - auto [result, nzcv] = - arithmeticHelp::addExtend_3ops(operands, metadata, true); + auto [result, nzcv] = arithmeticHelp::addExtend_3ops( + srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSXri: { // adds xd, xn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(operands, metadata, true); + arithmeticHelp::addShift_imm(srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_ADDSXrs: { // adds xd, xn, xm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_3ops(operands, metadata, true); + arithmeticHelp::addShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_ADDSXrx: // adds xd, xn, wm{, extend {#amount}} case Opcode::AArch64_ADDSXrx64: { // adds xd, xn, xm{, extend {#amount}} - auto [result, nzcv] = - arithmeticHelp::addExtend_3ops(operands, metadata, true); + auto [result, nzcv] = arithmeticHelp::addExtend_3ops( + srcRegVals, metadata, true); results[0] = nzcv; results[1] = RegisterValue(result, 8); break; } case Opcode::AArch64_ADDVL_XXI: { // addvl xd, xn, #imm - auto x = operands[0].get(); + auto x = srcRegVals[0].get(); auto y = static_cast(metadata.operands[2].imm); // convert VL from LEN (number of 128-bits) to bytes const uint64_t VL = VL_bits / 8; @@ -190,135 +192,140 @@ void Instruction::execute() { break; } case Opcode::AArch64_ADDVv4i16v: { // addv hd, vn.4h - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_ADDVv4i32v: { // addv sd, vn.4s - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_ADDVv8i8v: { // addv bd, vn.8b - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_ADDWri: { // add wd, wn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(operands, metadata, false); + arithmeticHelp::addShift_imm(srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrs: { // add wd, wn, wm{, shift #amount} - auto [result, nzcv] = - arithmeticHelp::addShift_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::addShift_3ops( + srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrx: { // add wd, wn, wm{, extend #amount} - auto [result, nzcv] = - arithmeticHelp::addExtend_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::addExtend_3ops( + srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDXri: { // add xd, xn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(operands, metadata, false); + arithmeticHelp::addShift_imm(srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADDXrs: { // add xd, xn, xm, {shift #amount} - auto [result, nzcv] = - arithmeticHelp::addShift_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::addShift_3ops( + srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADDXrx: // add xd, xn, wm{, extend {#amount}} case Opcode::AArch64_ADDXrx64: { // add xd, xn, xm{, extend {#amount}} - auto [result, nzcv] = - arithmeticHelp::addExtend_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::addExtend_3ops( + srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADD_ZI_B: { // add zdn.b, zdn.b, imm{, shift} - results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_D: { // add zdn.d, zdn.d, imm{, shift} - results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_H: { // add zdn.h zdn.h, imm{, shift} - results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_S: { // add zdn.s, zdn.s, imm{, shift} - results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_B: { // add zdn.b, pg/m, zdn.b, zm.b - results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_D: { // add zdn.d, pg/m, zdn.d, zm.d results[0] = - sveHelp::sveAddPredicated_vecs(operands, VL_bits); + sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_H: { // add zdn.h, pg/m, zdn.h, zm.h results[0] = - sveHelp::sveAddPredicated_vecs(operands, VL_bits); + sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_S: { // add zdn.s, pg/m, zdn.s, zm.s results[0] = - sveHelp::sveAddPredicated_vecs(operands, VL_bits); + sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_B: { // add zd.b, zn.b, zm.b - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_D: { // add zd.d, zn.d, zm.d - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_H: { // add zd.h, zn.h, zm.h - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_S: { // add zd.s, zn.s, zm.s - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_ADDv16i8: { // add vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv1i64: { // add dd, dn, dm - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv2i32: { // add vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv2i64: { // add vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv4i16: { // add vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv4i32: { // add vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv8i16: { // add vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADDv8i8: { // add vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_ADR: { // adr xd, #imm @@ -336,21 +343,21 @@ void Instruction::execute() { case Opcode::AArch64_ADR_LSL_ZZZ_D_1: // adr zd.d, [zn.d, zm.d, lsl #1] case Opcode::AArch64_ADR_LSL_ZZZ_D_2: // adr zd.d, [zn.d, zm.d, lsl #2] case Opcode::AArch64_ADR_LSL_ZZZ_D_3: { // adr zd.d, [zn.d, zm.d, lsl #3] - results[0] = sveHelp::sveAdr_packedOffsets(operands, metadata, - VL_bits); + results[0] = sveHelp::sveAdr_packedOffsets(srcRegVals, + metadata, VL_bits); break; } case Opcode::AArch64_ADR_LSL_ZZZ_S_0: // adr zd.s, [zn.s, zm.s] case Opcode::AArch64_ADR_LSL_ZZZ_S_1: // adr zd.s, [zn.s, zm.s, lsl #1] case Opcode::AArch64_ADR_LSL_ZZZ_S_2: // adr zd.s, [zn.s, zm.s, lsl #2] case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { // adr zd.s, [zn.s, zm.s, lsl #3] - results[0] = sveHelp::sveAdr_packedOffsets(operands, metadata, - VL_bits); + results[0] = sveHelp::sveAdr_packedOffsets(srcRegVals, + metadata, VL_bits); break; } case Opcode::AArch64_ANDSWri: { // ands wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, true, + srcRegVals, metadata, true, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = nzcv; results[1] = {result, 8}; @@ -358,7 +365,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSWrs: { // ands wd, wn, wm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, true, + srcRegVals, metadata, true, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = nzcv; results[1] = {result, 8}; @@ -366,7 +373,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSXri: { // ands xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, true, + srcRegVals, metadata, true, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = nzcv; results[1] = result; @@ -374,7 +381,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSXrs: { // ands xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, true, + srcRegVals, metadata, true, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = nzcv; results[1] = result; @@ -382,40 +389,40 @@ void Instruction::execute() { } case Opcode::AArch64_ANDWri: { // and wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ANDWrs: { // and wd, wn, wm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ANDXri: { // and xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = result; break; } case Opcode::AArch64_ANDXrs: { // and xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = result; break; } case Opcode::AArch64_AND_PPzPP: { // and pd.b, pg/z, pn.b, pm.b results[0] = sveHelp::sveLogicOp_preds( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); break; } case Opcode::AArch64_AND_ZI: { // and zdn, zdn, #imm - const uint64_t* dn = operands[0].getAsVector(); + const uint64_t* dn = srcRegVals[0].getAsVector(); const uint64_t imm = static_cast(metadata.operands[2].imm); const uint16_t partition_num = VL_bits / 64; @@ -428,44 +435,44 @@ void Instruction::execute() { } case Opcode::AArch64_AND_ZPmZ_B: { // and zdn.b, pg/m, zdn.b, zm.b results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_D: { // and zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_H: { // and zdn.h, pg/m, zdn.h, zm.h results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint16_t x, uint16_t y) -> uint16_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_S: { // and zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); break; } case Opcode::AArch64_ANDv16i8: { // and vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_ANDv8i8: { // and vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_ASRVWr: { // asrv wd, wn, wm - results[0] = {logicalHelp::asrv_3gpr(operands), 8}; + results[0] = {logicalHelp::asrv_3gpr(srcRegVals), 8}; break; } case Opcode::AArch64_ASRVXr: { // asrv xd, xn, xm - results[0] = logicalHelp::asrv_3gpr(operands); + results[0] = logicalHelp::asrv_3gpr(srcRegVals); break; } case Opcode::AArch64_B: { // b label @@ -474,68 +481,70 @@ void Instruction::execute() { break; } case Opcode::AArch64_BFMWri: { // bfm wd, wn, #immr, #imms - results[0] = { - bitmanipHelp::bfm_2imms(operands, metadata, false, false), - 8}; + results[0] = {bitmanipHelp::bfm_2imms(srcRegVals, metadata, + false, false), + 8}; break; } case Opcode::AArch64_BFMXri: { // bfm xd, xn, #immr, #imms - results[0] = - bitmanipHelp::bfm_2imms(operands, metadata, false, false); + results[0] = bitmanipHelp::bfm_2imms(srcRegVals, metadata, + false, false); break; } case Opcode::AArch64_BICSWrs: { // bics wd, wn, wm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(operands, metadata, true); + logicalHelp::bicShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_BICSXrs: { // bics xd, xn, xm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(operands, metadata, true); + logicalHelp::bicShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_BICWrs: { // bic wd, wn, wm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(operands, metadata, false); + logicalHelp::bicShift_3ops(srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_BICXrs: { // bic xd, xn, xm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(operands, metadata, false); + logicalHelp::bicShift_3ops(srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_BICv16i8: { // bic vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBic_3ops(operands); + results[0] = neonHelp::vecBic_3ops(srcRegVals); break; } case Opcode::AArch64_BICv4i32: { // bic vd.4s, #imm{, lsl #shift} - results[0] = neonHelp::vecBicShift_imm(operands, metadata); + results[0] = + neonHelp::vecBicShift_imm(srcRegVals, metadata); break; } case Opcode::AArch64_BICv8i16: { // bic vd.8h, #imm{, lsl #shift} - results[0] = neonHelp::vecBicShift_imm(operands, metadata); + results[0] = + neonHelp::vecBicShift_imm(srcRegVals, metadata); break; } case Opcode::AArch64_BICv8i8: { // bic vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecBic_3ops(operands); + results[0] = neonHelp::vecBic_3ops(srcRegVals); break; } case Opcode::AArch64_BIFv16i8: { // bif vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBitwiseInsert<16>(operands, true); + results[0] = neonHelp::vecBitwiseInsert<16>(srcRegVals, true); break; } case Opcode::AArch64_BITv16i8: { // bit vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBitwiseInsert<16>(operands, false); + results[0] = neonHelp::vecBitwiseInsert<16>(srcRegVals, false); break; } case Opcode::AArch64_BITv8i8: { // bit vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecBitwiseInsert<8>(operands, false); + results[0] = neonHelp::vecBitwiseInsert<8>(srcRegVals, false); break; } case Opcode::AArch64_BL: { // bl #imm @@ -546,13 +555,13 @@ void Instruction::execute() { } case Opcode::AArch64_BLR: { // blr xn branchTaken_ = true; - branchAddress_ = operands[0].get(); + branchAddress_ = srcRegVals[0].get(); results[0] = static_cast(instructionAddress_ + 4); break; } case Opcode::AArch64_BR: { // br xn branchTaken_ = true; - branchAddress_ = operands[0].get(); + branchAddress_ = srcRegVals[0].get(); break; } case Opcode::AArch64_BRK: { @@ -560,11 +569,12 @@ void Instruction::execute() { break; } case Opcode::AArch64_BSLv16i8: { // bsl vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBsl<16>(operands); + results[0] = neonHelp::vecBsl<16>(srcRegVals); break; } case Opcode::AArch64_Bcc: { // b.cond label - if (AuxFunc::conditionHolds(metadata.cc, operands[0].get())) { + if (AuxFunc::conditionHolds(metadata.cc, + srcRegVals[0].get())) { branchTaken_ = true; branchAddress_ = instructionAddress_ + metadata.operands[0].imm; } else { @@ -575,23 +585,23 @@ void Instruction::execute() { } case Opcode::AArch64_CASALW: { // casal ws, wt, [xn|sp] // LOAD / STORE - const uint32_t s = operands[0].get(); - const uint32_t t = operands[1].get(); + const uint32_t s = srcRegVals[0].get(); + const uint32_t t = srcRegVals[1].get(); const uint32_t n = memoryData[0].get(); if (n == s) memoryData[0] = t; break; } case Opcode::AArch64_CASALX: { // casal xs, xt, [xn|sp] // LOAD / STORE - const uint64_t s = operands[0].get(); - const uint64_t t = operands[1].get(); + const uint64_t s = srcRegVals[0].get(); + const uint64_t t = srcRegVals[1].get(); const uint64_t n = memoryData[0].get(); if (n == s) memoryData[0] = t; break; } case Opcode::AArch64_CBNZW: { // cbnz wn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - operands, metadata, instructionAddress_, + srcRegVals, metadata, instructionAddress_, [](uint32_t x) -> bool { return x != 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -599,7 +609,7 @@ void Instruction::execute() { } case Opcode::AArch64_CBNZX: { // cbnz xn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - operands, metadata, instructionAddress_, + srcRegVals, metadata, instructionAddress_, [](uint64_t x) -> bool { return x != 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -607,7 +617,7 @@ void Instruction::execute() { } case Opcode::AArch64_CBZW: { // cbz wn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - operands, metadata, instructionAddress_, + srcRegVals, metadata, instructionAddress_, [](uint32_t x) -> bool { return x == 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -615,85 +625,85 @@ void Instruction::execute() { } case Opcode::AArch64_CBZX: { // cbz xn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - operands, metadata, instructionAddress_, + srcRegVals, metadata, instructionAddress_, [](uint64_t x) -> bool { return x == 0; }); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_CCMNWi: { // ccmn wn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmn_imm(operands, metadata); + results[0] = conditionalHelp::ccmn_imm(srcRegVals, metadata); break; } case Opcode::AArch64_CCMNXi: { // ccmn xn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmn_imm(operands, metadata); + results[0] = conditionalHelp::ccmn_imm(srcRegVals, metadata); break; } case Opcode::AArch64_CCMPWi: { // ccmp wn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmp_imm(operands, metadata); + results[0] = conditionalHelp::ccmp_imm(srcRegVals, metadata); break; } case Opcode::AArch64_CCMPWr: { // ccmp wn, wm, #nzcv, cc - results[0] = conditionalHelp::ccmp_reg(operands, metadata); + results[0] = conditionalHelp::ccmp_reg(srcRegVals, metadata); break; } case Opcode::AArch64_CCMPXi: { // ccmp xn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmp_imm(operands, metadata); + results[0] = conditionalHelp::ccmp_imm(srcRegVals, metadata); break; } case Opcode::AArch64_CCMPXr: { // ccmp xn, xm, #nzcv, cc - results[0] = conditionalHelp::ccmp_reg(operands, metadata); + results[0] = conditionalHelp::ccmp_reg(srcRegVals, metadata); break; } case Opcode::AArch64_CLZXr: { // clz xd, xn - results[0] = arithmeticHelp::clz_reg(operands); + results[0] = arithmeticHelp::clz_reg(srcRegVals); break; } case Opcode::AArch64_CMEQv16i8: { // cmeq vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecCompare( - operands, false, + srcRegVals, false, [](uint8_t x, uint8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv16i8rz: { // cmeq vd.16b, vn.16b, #0 results[0] = neonHelp::vecCompare( - operands, true, + srcRegVals, true, [](uint8_t x, uint8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv4i32: { // cmeq vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecCompare( - operands, false, + srcRegVals, false, [](uint32_t x, uint32_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv8i8: { // cmeq vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecCompare( - operands, false, + srcRegVals, false, [](int8_t x, int8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv8i8rz: { // cmeq vd.8b, vn.8b, #0 results[0] = neonHelp::vecCompare( - operands, true, + srcRegVals, true, [](int8_t x, int8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMHIv4i32: { // cmhi vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecCompare( - operands, false, + srcRegVals, false, [](uint32_t x, uint32_t y) -> bool { return (x > y); }); break; } case Opcode::AArch64_CMHSv16i8: { // cmhs vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecCompare( - operands, false, + srcRegVals, false, [](int8_t x, int8_t y) -> bool { return (x >= y); }); break; } case Opcode::AArch64_CMPEQ_PPzZI_B: { // cmpeq pd.b, pg/z, zn.b, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](uint8_t x, uint8_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -701,7 +711,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_D: { // cmpeq pd.d, pg/z, zn.d, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](uint64_t x, uint64_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -709,7 +719,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_H: { // cmpeq pd.h, pg/z, zn.h, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](uint16_t x, uint16_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -717,7 +727,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_S: { // cmpeq pd.s, pg/z, zn.s, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](uint32_t x, uint32_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -725,7 +735,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_B: { // cmpeq pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint8_t x, uint8_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -733,7 +743,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_D: { // cmpeq pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint64_t x, uint64_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -741,7 +751,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_H: { // cmpeq pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint16_t x, uint16_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -749,7 +759,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_S: { // cmpeq pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint32_t x, uint32_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -757,7 +767,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_B: { // cmpgt pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int8_t x, int8_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -765,7 +775,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_D: { // cmpgt pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int64_t x, int64_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -773,7 +783,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_H: { // cmpgt pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int16_t x, int16_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -781,7 +791,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_S: { // cmpgt pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int32_t x, int32_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -789,7 +799,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_B: { // cmphi pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint8_t x, uint8_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -797,7 +807,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_D: { // cmphi pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint64_t x, uint64_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -805,7 +815,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_H: { // cmphi pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint16_t x, uint16_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -813,7 +823,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_S: { // cmphi pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](uint32_t x, uint32_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -821,7 +831,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_B: { // cmpne pd.b, pg/z. zn.b, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](int8_t x, int8_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -829,7 +839,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_D: { // cmpne pd.d, pg/z. zn.d, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](int64_t x, int64_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -837,7 +847,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_H: { // cmpne pd.h, pg/z. zn.h, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](int16_t x, int16_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -845,7 +855,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_S: { // cmpne pd.s, pg/z. zn.s, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](int32_t x, int32_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -853,7 +863,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_B: { // cmpne pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int8_t x, int8_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -861,7 +871,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_D: { // cmpne pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int64_t x, int64_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -869,7 +879,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_H: { // cmpne pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int16_t x, int16_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -877,7 +887,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_S: { // cmpne pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](int32_t x, int32_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -896,19 +906,19 @@ void Instruction::execute() { break; } case Opcode::AArch64_CNTP_XPP_B: { // cntp xd, pg, pn.b - results[0] = sveHelp::sveCntp(operands, VL_bits); + results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_D: { // cntp xd, pg, pn.d - results[0] = sveHelp::sveCntp(operands, VL_bits); + results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_H: { // cntp xd, pg, pn.h - results[0] = sveHelp::sveCntp(operands, VL_bits); + results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_S: { // cntp xd, pg, pn.s - results[0] = sveHelp::sveCntp(operands, VL_bits); + results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); break; } case Opcode::AArch64_CNTW_XPiI: { // cntw xd{, pattern{, #imm}} @@ -916,91 +926,94 @@ void Instruction::execute() { break; } case Opcode::AArch64_CNTv8i8: { // cnt vd.8b, vn.8b - results[0] = neonHelp::vecCountPerByte(operands); + results[0] = neonHelp::vecCountPerByte(srcRegVals); break; } case Opcode::AArch64_CPY_ZPzI_B: { // cpy zd.b, pg/z, #imm{, shift} - results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); + results[0] = sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_D: { // cpy zd.d, pg/z, #imm{, shift} - results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_H: { // cpy zd.h, pg/z, #imm{, shift} - results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_S: { // cpy zd.s, pg/z, #imm{, shift} - results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_DUPi32: { // dup vd, vn.s[index] - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, false); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, false); break; } case Opcode::AArch64_DUPi64: { // dup vd, vn.d[index] - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, false); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, false); break; } case Opcode::AArch64_CSELWr: { // csel wd, wn, wm, cc results[0] = { conditionalHelp::cs_4ops( - operands, metadata, [](uint32_t x) -> uint32_t { return x; }), + srcRegVals, metadata, [](uint32_t x) -> uint32_t { return x; }), 8}; break; } case Opcode::AArch64_CSELXr: { // csel xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - operands, metadata, [](uint64_t x) -> uint64_t { return x; }); + srcRegVals, metadata, [](uint64_t x) -> uint64_t { return x; }); break; } case Opcode::AArch64_CSINCWr: { // csinc wd, wn, wm, cc results[0] = {conditionalHelp::cs_4ops( - operands, metadata, + srcRegVals, metadata, [](uint32_t x) -> uint32_t { return x + 1; }), 8}; break; } case Opcode::AArch64_CSINCXr: { // csinc xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - operands, metadata, [](uint64_t x) -> uint64_t { return x + 1; }); + srcRegVals, metadata, [](uint64_t x) -> uint64_t { return x + 1; }); break; } case Opcode::AArch64_CSINVWr: { // csinv wd, wn, wm, cc - results[0] = { - conditionalHelp::cs_4ops( - operands, metadata, [](uint32_t x) -> uint32_t { return ~x; }), - 8}; + results[0] = {conditionalHelp::cs_4ops( + srcRegVals, metadata, + [](uint32_t x) -> uint32_t { return ~x; }), + 8}; break; } case Opcode::AArch64_CSINVXr: { // csinv xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - operands, metadata, [](uint64_t x) -> uint64_t { return ~x; }); + srcRegVals, metadata, [](uint64_t x) -> uint64_t { return ~x; }); break; } case Opcode::AArch64_CSNEGWr: { // csneg wd, wn, wm, cc results[0] = { conditionalHelp::cs_4ops( - operands, metadata, [](int32_t x) -> int32_t { return -x; }), + srcRegVals, metadata, [](int32_t x) -> int32_t { return -x; }), 8}; break; } case Opcode::AArch64_CSNEGXr: { // csneg xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - operands, metadata, [](uint64_t x) -> uint64_t { return -x; }); + srcRegVals, metadata, [](uint64_t x) -> uint64_t { return -x; }); break; } case Opcode::AArch64_DECB_XPiI: { // decb xdn{, pattern{, MUL #imm}} results[0] = - sveHelp::sveDec_scalar(operands, metadata, VL_bits); + sveHelp::sveDec_scalar(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_DECD_XPiI: { // decd xdn{, pattern{, MUL #imm}} results[0] = - sveHelp::sveDec_scalar(operands, metadata, VL_bits); + sveHelp::sveDec_scalar(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_DMB: { // dmb option|#imm @@ -1017,48 +1030,48 @@ void Instruction::execute() { break; } case Opcode::AArch64_DUP_ZI_B: { // dup zd.b, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_D: { // dup zd.d, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_H: { // dup zd.h, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_S: { // dup zd.s, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZR_B: { // dup zd.b, wn - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_D: { // dup zd.d, xn - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_H: { // dup zd.h, wn - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_S: { // dup zd.s, wn - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZZI_D: { // dup zd.d, zn.d[#imm] results[0] = - sveHelp::sveDup_vecIndexed(operands, metadata, VL_bits); + sveHelp::sveDup_vecIndexed(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_DUP_ZZI_Q: { // dup zd.q, zn.q[#imm] @@ -1066,7 +1079,7 @@ void Instruction::execute() { // can use uint64_t. const uint16_t index = 2 * static_cast(metadata.operands[1].vector_index); - const uint64_t* n = operands[0].getAsVector(); + const uint64_t* n = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 128; uint64_t out[32] = {0}; @@ -1084,126 +1097,126 @@ void Instruction::execute() { } case Opcode::AArch64_DUP_ZZI_S: { // dup zd.s, zn.s[#imm] results[0] = - sveHelp::sveDup_vecIndexed(operands, metadata, VL_bits); + sveHelp::sveDup_vecIndexed(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_DUPv16i8gpr: { // dup vd.16b, wn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_DUPv2i32gpr: { // dup vd.2s, wn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_DUPv2i32lane: { // dup vd.2s, vn.s[index] - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, false); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, false); break; } case Opcode::AArch64_DUPv2i64gpr: { // dup vd.2d, xn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_DUPv2i64lane: { // dup vd.2d, vn.d[index] - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, false); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, false); break; } case Opcode::AArch64_DUPv4i16gpr: { // dup vd.4h, wn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_DUPv4i32gpr: { // dup vd.4s, wn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_DUPv4i32lane: { // dup vd.4s, vn.s[index] - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, false); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, false); break; } case Opcode::AArch64_DUPv8i16gpr: { // dup vd.8h, wn - results[0] = - neonHelp::vecDup_gprOrIndex(operands, metadata, true); + results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, + metadata, true); break; } case Opcode::AArch64_EORWri: { // eor wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_EORWrs: { // eor wd, wn, wm{, shift #imm} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_EORXri: { // eor xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); results[0] = result; break; } case Opcode::AArch64_EORXrs: { // eor xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); results[0] = result; break; } case Opcode::AArch64_EOR_PPzPP: { results[0] = sveHelp::sveLogicOp_preds( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_B: { // eor zdn.b, pg/m, zdn.b, zm.b results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_D: { // eor zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_H: { // eor zdn.h, pg/m, zdn.h, zm.h results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint16_t x, uint16_t y) -> uint16_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_S: { // eor zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZZZ: { // eor zd.d, zn.d, zm.d results[0] = sveHelp::sveLogicOpUnPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EORv16i8: { // eor vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EORv8i8: { // eor vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { // MOVA zd.b, pg/m, zanh.b[ws, @@ -1214,13 +1227,13 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 8; - const uint8_t* zd = operands[0].getAsVector(); - const uint64_t* pg = operands[1].getAsVector(); + const uint8_t* zd = srcRegVals[0].getAsVector(); + const uint64_t* pg = srcRegVals[1].getAsVector(); const uint64_t sliceNum = - (operands[2 + rowCount].get() + + (srcRegVals[2 + rowCount].get() + static_cast(metadata.operands[2].sme_index.disp)) % rowCount; - const uint8_t* zanRow = operands[2 + sliceNum].getAsVector(); + const uint8_t* zanRow = srcRegVals[2 + sliceNum].getAsVector(); uint8_t out[256] = {0}; for (int elem = 0; elem < rowCount; elem++) { @@ -1236,638 +1249,651 @@ void Instruction::execute() { } case Opcode::AArch64_EXTRWrri: { // extr wd, wn, wm, #lsb results[0] = { - bitmanipHelp::extrLSB_registers(operands, metadata), 8}; + bitmanipHelp::extrLSB_registers(srcRegVals, metadata), 8}; break; } case Opcode::AArch64_EXTRXrri: { // extr xd, xn, xm, #lsb results[0] = - bitmanipHelp::extrLSB_registers(operands, metadata); + bitmanipHelp::extrLSB_registers(srcRegVals, metadata); break; } case Opcode::AArch64_EXTv16i8: { // ext vd.16b, vn.16b, vm.16b, #index results[0] = - neonHelp::vecExtVecs_index(operands, metadata); + neonHelp::vecExtVecs_index(srcRegVals, metadata); break; } case Opcode::AArch64_EXTv8i8: { // ext vd.8b, vn.8b, vm.8b, #index - results[0] = neonHelp::vecExtVecs_index(operands, metadata); + results[0] = + neonHelp::vecExtVecs_index(srcRegVals, metadata); break; } case Opcode::AArch64_FABDv2f64: { // fabd vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFabd(operands); + results[0] = neonHelp::vecFabd(srcRegVals); break; } case Opcode::AArch64_FABDv4f32: { // fabd vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFabd(operands); + results[0] = neonHelp::vecFabd(srcRegVals); break; } case Opcode::AArch64_FABD32: { // fabd sd, sn, sm - results[0] = floatHelp::fabd_3ops(operands); + results[0] = floatHelp::fabd_3ops(srcRegVals); break; } case Opcode::AArch64_FABD64: { // fabd dd, dn, dm - results[0] = floatHelp::fabd_3ops(operands); + results[0] = floatHelp::fabd_3ops(srcRegVals); break; } case Opcode::AArch64_FABSDr: { // fabs dd, dn - results[0] = floatHelp::fabs_2ops(operands); + results[0] = floatHelp::fabs_2ops(srcRegVals); break; } case Opcode::AArch64_FABSSr: { // fabs sd, sn - results[0] = floatHelp::fabs_2ops(operands); + results[0] = floatHelp::fabs_2ops(srcRegVals); break; } case Opcode::AArch64_FABS_ZPmZ_D: { // fabs zd.d, pg/m, zn.d - results[0] = sveHelp::sveFabsPredicated(operands, VL_bits); + results[0] = sveHelp::sveFabsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FABS_ZPmZ_S: { // fabs zd.s, pg/m, zn.s - results[0] = sveHelp::sveFabsPredicated(operands, VL_bits); + results[0] = sveHelp::sveFabsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FABSv2f64: { // fabs vd.2d, vn.2d - results[0] = neonHelp::vecFabs_2ops(operands); + results[0] = neonHelp::vecFabs_2ops(srcRegVals); break; } case Opcode::AArch64_FABSv4f32: { // fabs vd.4s, vn.4s - results[0] = neonHelp::vecFabs_2ops(operands); + results[0] = neonHelp::vecFabs_2ops(srcRegVals); break; } case Opcode::AArch64_FADDA_VPZ_D: { // fadda dd, pg/m, dn, zm.d - results[0] = sveHelp::sveFaddaPredicated(operands, VL_bits); + results[0] = sveHelp::sveFaddaPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADDA_VPZ_S: { // fadda sd, pg/m, sn, zm.s - results[0] = sveHelp::sveFaddaPredicated(operands, VL_bits); + results[0] = sveHelp::sveFaddaPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADDDrr: { // fadd dd, dn, dm - results[0] = {arithmeticHelp::add_3ops(operands), 256}; + results[0] = {arithmeticHelp::add_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FADDPv2f32: { // faddp vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_FADDPv2f64: { // faddp vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_FADDPv2i32p: { // faddp dd, vn.2s - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_FADDPv2i64p: { // faddp dd, vn.2d - results[0] = neonHelp::vecSumElems_2ops(operands); + results[0] = neonHelp::vecSumElems_2ops(srcRegVals); break; } case Opcode::AArch64_FADDPv4f32: { // faddp vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAddp_3ops(operands); + results[0] = neonHelp::vecAddp_3ops(srcRegVals); break; } case Opcode::AArch64_FADDSrr: { // fadd sd, sn, sm - results[0] = {arithmeticHelp::add_3ops(operands), 256}; + results[0] = {arithmeticHelp::add_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FADD_ZPmI_D: { // fadd zdn.d, pg/m, zdn.d, const - results[0] = sveHelp::sveAddPredicated_const(operands, metadata, - VL_bits); + results[0] = sveHelp::sveAddPredicated_const(srcRegVals, + metadata, VL_bits); break; } case Opcode::AArch64_FADD_ZPmI_S: { // fadd zdn.s, pg/m, zdn.s, const - results[0] = - sveHelp::sveAddPredicated_const(operands, metadata, VL_bits); + results[0] = sveHelp::sveAddPredicated_const(srcRegVals, + metadata, VL_bits); break; } case Opcode::AArch64_FADD_ZPmZ_D: { // fadd zdn.d, pg/m, zdn.d, zm.d - results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADD_ZPmZ_S: { // fadd zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); + results[0] = sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADD_ZZZ_D: { // fadd zd.d, zn.d, zm.d - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADD_ZZZ_S: { // fadd zd.s, zn.s, zm.s - results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); + results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_FADDv2f32: { // fadd vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_FADDv2f64: { // fadd vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_FADDv4f32: { // fadd vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAdd_3ops(operands); + results[0] = neonHelp::vecAdd_3ops(srcRegVals); break; } case Opcode::AArch64_FCADD_ZPmZ_D: { // fcadd zdn.d, pg/m, zdn.d, zm.d, // #imm results[0] = - sveHelp::sveFcaddPredicated(operands, metadata, VL_bits); + sveHelp::sveFcaddPredicated(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FCCMPDrr: // fccmp sn, sm, #nzcv, cc case Opcode::AArch64_FCCMPEDrr: { // fccmpe sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(operands, metadata); + results[0] = floatHelp::fccmp(srcRegVals, metadata); break; } case Opcode::AArch64_FCCMPESrr: { // fccmpe sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(operands, metadata); + results[0] = floatHelp::fccmp(srcRegVals, metadata); break; } case Opcode::AArch64_FCCMPSrr: { // fccmp sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(operands, metadata); + results[0] = floatHelp::fccmp(srcRegVals, metadata); break; } case Opcode::AArch64_FCMEQv2i32rz: { // fcmeq vd.2s, vd.2s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x == y; }); + srcRegVals, true, [](float x, float y) -> bool { return x == y; }); break; } case Opcode::AArch64_FCMEQv4i32rz: { // fcmeq vd.4s vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x == y; }); + srcRegVals, true, [](float x, float y) -> bool { return x == y; }); break; } case Opcode::AArch64_FCMGE_PPzZ0_D: { // fcmge pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZ0_S: { // fcmge pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZZ_D: { // fcmge pd.d, pg/z, zn.d, zm.d results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZZ_S: { // fcmge pd.s, pg/z, zn.s, zm.s results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2f32: { // fcmge vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecFCompare( - operands, false, [](float x, float y) -> bool { return x >= y; }); + srcRegVals, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2f64: { // fcmge vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecFCompare( - operands, false, [](float x, double y) -> bool { return x >= y; }); + srcRegVals, false, + [](float x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2i64rz: { // fcmge vd.2d, vn.2d, 0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](double x, double y) -> bool { return x >= y; }); + srcRegVals, true, + [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv4f32: { // fcmge vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecFCompare( - operands, false, [](float x, float y) -> bool { return x >= y; }); + srcRegVals, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv4i32rz: { // fcmge vd.4s, vn.4s, 0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x >= y; }); + srcRegVals, true, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGT_PPzZ0_D: { // fcmgt pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZ0_S: { // fcmgt pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZZ_D: { // fcmgt pd.d, pg/z, zn.d, zm.d results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZZ_S: { // fcmgt pd.s, pg/z, zn.s, zm. results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, false, + srcRegVals, metadata, VL_bits, false, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2i32rz: { // fcmgt vd.2s, vn.2s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x > y; }); + srcRegVals, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2i64rz: { // fcmgt vd.2d, vn.2d, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](double x, double y) -> bool { return x > y; }); + srcRegVals, true, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2f64: { // fcmgt vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecFCompare( - operands, false, [](double x, double y) -> bool { return x > y; }); + srcRegVals, false, + [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv4f32: { // fcmgt vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecFCompare( - operands, false, [](float x, float y) -> bool { return x > y; }); + srcRegVals, false, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv4i32rz: { // fcmgt vd.4s, vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x > y; }); + srcRegVals, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMLA_ZPmZZ_D: { // fcmla zda, pg/m, zn, zm, #imm results[0] = - sveHelp::sveFcmlaPredicated(operands, metadata, VL_bits); + sveHelp::sveFcmlaPredicated(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FCMLE_PPzZ0_D: { // fcmle pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](double x, double y) -> bool { return x <= y; }); break; } case Opcode::AArch64_FCMLE_PPzZ0_S: { // fcmle pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](float x, float y) -> bool { return x <= y; }); break; } case Opcode::AArch64_FCMLT_PPzZ0_S: { // fcmlt pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - operands, metadata, VL_bits, true, + srcRegVals, metadata, VL_bits, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv2i32rz: { // fcmlt vd.2s, vn.2s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x < y; }); + srcRegVals, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv2i64rz: { // fcmlt vd.2d, vn.2d, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](double x, double y) -> bool { return x < y; }); + srcRegVals, true, [](double x, double y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv4i32rz: { // fcmlt vd.4s, vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - operands, true, [](float x, float y) -> bool { return x < y; }); + srcRegVals, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMPDri: { // fcmp dn, #imm - results[0] = floatHelp::fcmp(operands, true); + results[0] = floatHelp::fcmp(srcRegVals, true); break; } case Opcode::AArch64_FCMPDrr: { // fcmp dn, dm - results[0] = floatHelp::fcmp(operands, false); + results[0] = floatHelp::fcmp(srcRegVals, false); break; } case Opcode::AArch64_FCMPEDri: { // fcmpe dn, #imm - results[0] = floatHelp::fcmp(operands, true); + results[0] = floatHelp::fcmp(srcRegVals, true); break; } case Opcode::AArch64_FCMPEDrr: { // fcmpe dn, dm - results[0] = floatHelp::fcmp(operands, false); + results[0] = floatHelp::fcmp(srcRegVals, false); break; } case Opcode::AArch64_FCMPESri: { // fcmpe sn, #imm - results[0] = floatHelp::fcmp(operands, true); + results[0] = floatHelp::fcmp(srcRegVals, true); break; } case Opcode::AArch64_FCMPESrr: { // fcmpe sn, sm - results[0] = floatHelp::fcmp(operands, false); + results[0] = floatHelp::fcmp(srcRegVals, false); break; } case Opcode::AArch64_FCMPSri: { // fcmp sn, #imm - results[0] = floatHelp::fcmp(operands, true); + results[0] = floatHelp::fcmp(srcRegVals, true); break; } case Opcode::AArch64_FCMPSrr: { // fcmp sn, sm - results[0] = floatHelp::fcmp(operands, false); + results[0] = floatHelp::fcmp(srcRegVals, false); break; } case Opcode::AArch64_FCPY_ZPmI_D: { // fcpy zd.d, pg/m, #const - results[0] = sveHelp::sveFcpy_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveFcpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FCPY_ZPmI_S: { // fcpy zd.s, pg/m, #const - results[0] = sveHelp::sveFcpy_imm(operands, metadata, VL_bits); + results[0] = sveHelp::sveFcpy_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FCSELDrrr: { // fcsel dd, dn, dm, cond results[0] = { conditionalHelp::cs_4ops( - operands, metadata, [](double x) -> double { return x; }), + srcRegVals, metadata, [](double x) -> double { return x; }), 256}; break; } case Opcode::AArch64_FCSELSrrr: { // fcsel sd, sn, sm, cond results[0] = { - conditionalHelp::cs_4ops(operands, metadata, + conditionalHelp::cs_4ops(srcRegVals, metadata, [](float x) -> float { return x; }), 256}; break; } case Opcode::AArch64_FCVTASUWDr: { // fcvtas wd, dn - results[0] = {static_cast(round(operands[0].get())), + results[0] = {static_cast(round(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTASUXDr: { // fcvtas xd, dn - results[0] = static_cast(round(operands[0].get())); + results[0] = static_cast(round(srcRegVals[0].get())); break; } case Opcode::AArch64_FCVTDSr: { // fcvt dd, sn // TODO: Handle NaNs, denorms, and saturation? - results[0] = neonHelp::vecFcvtl(operands, false); + results[0] = neonHelp::vecFcvtl(srcRegVals, false); break; } case Opcode::AArch64_FCVTLv2i32: { // fcvtl vd.2d, vn.2s - results[0] = neonHelp::vecFcvtl(operands, false); + results[0] = neonHelp::vecFcvtl(srcRegVals, false); break; } case Opcode::AArch64_FCVTLv4i32: { // fcvtl2 vd.2d, vn.4s - results[0] = neonHelp::vecFcvtl(operands, true); + results[0] = neonHelp::vecFcvtl(srcRegVals, true); break; } case Opcode::AArch64_FCVTNv2i32: { // fcvtn vd.2s, vn.2d - results[0] = neonHelp::vecFcvtn(operands, false); + results[0] = neonHelp::vecFcvtn(srcRegVals, false); break; } case Opcode::AArch64_FCVTNv4i32: { // fcvtn2 vd.4s, vn.2d - results[0] = neonHelp::vecFcvtn(operands, true); + results[0] = neonHelp::vecFcvtn(srcRegVals, true); break; } case Opcode::AArch64_FCVTSDr: { // fcvt sd, dn // TODO: Handle NaNs, denorms, and saturation? - results[0] = neonHelp::vecFcvtl(operands, false); + results[0] = neonHelp::vecFcvtl(srcRegVals, false); break; } case Opcode::AArch64_FCVTZSUWDr: { // fcvtzs wd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 8}; + static_cast(std::trunc(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTZSUWSr: { // fcvtzs wd, sn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 8}; + static_cast(std::trunc(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTZSUXDr: { // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 8}; + static_cast(std::trunc(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: { // fcvtzs zd.d, pg/m, zn.d results[0] = - sveHelp::sveFcvtzsPredicated(operands, VL_bits); + sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: { // fcvtzs zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtzsPredicated(operands, VL_bits); + sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_StoD: { // fcvtzs zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtzsPredicated(operands, VL_bits); + sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_StoS: { // fcvtzs zd.s, pg/m, zn.s results[0] = - sveHelp::sveFcvtzsPredicated(operands, VL_bits); + sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FCVTZSv2f64: { // fcvtzs vd.2d, vn.2d - results[0] = neonHelp::vecFcvtzs(operands); + results[0] = neonHelp::vecFcvtzs(srcRegVals); break; } case Opcode::AArch64_FCVTZUUWDr: { // fcvtzu wd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 8}; + static_cast(std::trunc(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTZUUWSr: { // fcvtzu wd, sn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 8}; + static_cast(std::trunc(srcRegVals[0].get())), 8}; break; } case Opcode::AArch64_FCVTZUUXDr: { // fcvtzu xd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = - static_cast(std::trunc(operands[0].get())); + static_cast(std::trunc(srcRegVals[0].get())); break; } case Opcode::AArch64_FCVTZUUXSr: { // fcvtzu xd, sn // TODO: Handle NaNs, denorms, and saturation - results[0] = static_cast(std::trunc(operands[0].get())); + results[0] = + static_cast(std::trunc(srcRegVals[0].get())); break; } case Opcode::AArch64_FCVTZUv1i64: { // fcvtzu dd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(operands[0].get())), 256}; + static_cast(std::trunc(srcRegVals[0].get())), + 256}; break; } case Opcode::AArch64_FCVT_ZPmZ_DtoS: { // fcvt zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FCVT_ZPmZ_StoD: { // fcvt zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FDIVDrr: { // fdiv dd, dn, dm - results[0] = {divideHelp::div_3ops(operands), 256}; + results[0] = {divideHelp::div_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FDIVR_ZPmZ_D: { // fdivr zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](double x, double y) -> double { return (y / x); }); break; } case Opcode::AArch64_FDIVR_ZPmZ_S: { // fdivr zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](float x, float y) -> float { return (y / x); }); break; } case Opcode::AArch64_FDIVSrr: { // fdiv sd, sn, sm - results[0] = {divideHelp::div_3ops(operands), 256}; + results[0] = {divideHelp::div_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FDIV_ZPmZ_D: { // fdiv zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](double x, double y) -> double { return (x / y); }); break; } case Opcode::AArch64_FDIVv2f64: { // fdiv vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return x / y; }); + srcRegVals, [](double x, double y) -> double { return x / y; }); break; } case Opcode::AArch64_FDUP_ZI_D: { // fdup zd.d, #imm - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_FDUP_ZI_S: { // fdup zd.s, #imm - results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, + results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_FMADDDrrr: { // fmadd dn, dm, da - results[0] = {multiplyHelp::madd_4ops(operands), 256}; + results[0] = {multiplyHelp::madd_4ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMADDSrrr: { // fmadd sn, sm, sa - results[0] = {multiplyHelp::madd_4ops(operands), 256}; + results[0] = {multiplyHelp::madd_4ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMAD_ZPmZZ_D: { // fmad zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveFmadPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmadPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMAD_ZPmZZ_S: { // fmad zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveFmadPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmadPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMAXNMDrr: { // fmaxnm dd, dn, dm - results[0] = floatHelp::fmaxnm_3ops(operands); + results[0] = floatHelp::fmaxnm_3ops(srcRegVals); break; } case Opcode::AArch64_FMAXNMPv2i64p: { // fmaxnmp dd, vd.2d - results[0] = neonHelp::vecMaxnmp_2ops(operands); + results[0] = neonHelp::vecMaxnmp_2ops(srcRegVals); break; } case Opcode::AArch64_FMAXNMSrr: { // fmaxnm sd, sn, sm - results[0] = floatHelp::fmaxnm_3ops(operands); + results[0] = floatHelp::fmaxnm_3ops(srcRegVals); break; } case Opcode::AArch64_FMAXNMv2f64: { // fmaxnm vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, + srcRegVals, [](double x, double y) -> double { return std::fmax(x, y); }); break; } case Opcode::AArch64_FMINNMDrr: { // fminnm dd, dn, dm - results[0] = floatHelp::fminnm_3ops(operands); + results[0] = floatHelp::fminnm_3ops(srcRegVals); break; } case Opcode::AArch64_FMINNMPv2i64p: { // fminnmp dd, vd.2d - results[0] = neonHelp::vecMinv_2ops(operands); + results[0] = neonHelp::vecMinv_2ops(srcRegVals); break; } case Opcode::AArch64_FMINNMSrr: { // fminnm sd, sn, sm - results[0] = floatHelp::fminnm_3ops(operands); + results[0] = floatHelp::fminnm_3ops(srcRegVals); break; } case Opcode::AArch64_FMINNMv2f64: { // fminnm vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, + srcRegVals, [](double x, double y) -> double { return std::fmin(x, y); }); break; } case Opcode::AArch64_FMLA_ZPmZZ_D: { // fmla zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMLA_ZPmZZ_S: { // fmla zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + results[0] = sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMLAv2f32: { // fmla vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecFmla_3vecs(operands); + results[0] = neonHelp::vecFmla_3vecs(srcRegVals); break; } case Opcode::AArch64_FMLA_ZZZI_D: { // fmla zda.d, zn.d, zm.d[index] results[0] = - sveHelp::sveMlaIndexed_vecs(operands, metadata, VL_bits); + sveHelp::sveMlaIndexed_vecs(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FMLA_ZZZI_S: { // fmla zda.s, zn.s, zm.s[index] results[0] = - sveHelp::sveMlaIndexed_vecs(operands, metadata, VL_bits); + sveHelp::sveMlaIndexed_vecs(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FMLAv2f64: { // fmla vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFmla_3vecs(operands); + results[0] = neonHelp::vecFmla_3vecs(srcRegVals); break; } case Opcode::AArch64_FMLAv2i32_indexed: { // fmla vd.2s, vn.2s, // vm.2s[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(operands, metadata); + neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMLAv2i64_indexed: { // fmla vd.2d, vn.2d, // vm.d[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(operands, metadata); + neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMLAv4f32: { // fmla vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFmla_3vecs(operands); + results[0] = neonHelp::vecFmla_3vecs(srcRegVals); break; } case Opcode::AArch64_FMLAv4i32_indexed: { // fmla vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(operands, metadata); + neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMLS_ZPmZZ_D: { // fmls zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveFmlsPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmlsPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMLS_ZPmZZ_S: { // fmls zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveFmlsPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmlsPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMLSv2f64: { // fmls vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFmls_3vecs(operands); + results[0] = neonHelp::vecFmls_3vecs(srcRegVals); break; } case Opcode::AArch64_FMLSv2i64_indexed: { results[0] = - neonHelp::vecFmlsIndexed_3vecs(operands, metadata); + neonHelp::vecFmlsIndexed_3vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMLSv4f32: { // fmls vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFmls_3vecs(operands); + results[0] = neonHelp::vecFmls_3vecs(srcRegVals); break; } case Opcode::AArch64_FMLSv4i32_indexed: { // fmls vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmlsIndexed_3vecs(operands, metadata); + neonHelp::vecFmlsIndexed_3vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMOPA_MPPZZ_D: { // fmopa zada.d, pn/m, pm/m, zn.d, @@ -1878,16 +1904,16 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 64; - const uint64_t* pn = operands[rowCount].getAsVector(); - const uint64_t* pm = operands[rowCount + 1].getAsVector(); - const double* zn = operands[rowCount + 2].getAsVector(); - const double* zm = operands[rowCount + 3].getAsVector(); + const uint64_t* pn = srcRegVals[rowCount].getAsVector(); + const uint64_t* pm = srcRegVals[rowCount + 1].getAsVector(); + const double* zn = srcRegVals[rowCount + 2].getAsVector(); + const double* zm = srcRegVals[rowCount + 3].getAsVector(); // zn is row, zm is col for (int row = 0; row < rowCount; row++) { double outRow[32] = {0}; uint64_t shifted_active_row = 1ull << ((row % 8) * 8); - const double* zadaRow = operands[row].getAsVector(); + const double* zadaRow = srcRegVals[row].getAsVector(); for (int col = 0; col < rowCount; col++) { double zadaElem = zadaRow[col]; uint64_t shifted_active_col = 1ull << ((col % 8) * 8); @@ -1909,16 +1935,16 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 32; - const uint64_t* pn = operands[rowCount].getAsVector(); - const uint64_t* pm = operands[rowCount + 1].getAsVector(); - const float* zn = operands[rowCount + 2].getAsVector(); - const float* zm = operands[rowCount + 3].getAsVector(); + const uint64_t* pn = srcRegVals[rowCount].getAsVector(); + const uint64_t* pm = srcRegVals[rowCount + 1].getAsVector(); + const float* zn = srcRegVals[rowCount + 2].getAsVector(); + const float* zm = srcRegVals[rowCount + 3].getAsVector(); // zn is row, zm is col for (int row = 0; row < rowCount; row++) { float outRow[64] = {0}; uint64_t shifted_active_row = 1ull << ((row % 16) * 4); - const float* zadaRow = operands[row].getAsVector(); + const float* zadaRow = srcRegVals[row].getAsVector(); for (int col = 0; col < rowCount; col++) { float zadaElem = zadaRow[col]; uint64_t shifted_active_col = 1ull << ((col % 16) * 4); @@ -1933,11 +1959,11 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVDXHighr: { // fmov xd, vn.d[1] - results[0] = operands[0].getAsVector()[1]; + results[0] = srcRegVals[0].getAsVector()[1]; break; } case Opcode::AArch64_FMOVDXr: { // fmov xd, dn - results[0] = operands[0].get(); + results[0] = srcRegVals[0].get(); break; } case Opcode::AArch64_FMOVDi: { // fmov dn, #imm @@ -1945,11 +1971,11 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVDr: { // fmov dd, dn - results[0] = {operands[0].get(), 256}; + results[0] = {srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FMOVSWr: { // fmov wd, sn - results[0] = {operands[0].get(), 8}; + results[0] = {srcRegVals[0].get(), 8}; break; } case Opcode::AArch64_FMOVSi: { // fmov sn, #imm @@ -1957,20 +1983,21 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVSr: { // fmov sd, sn - results[0] = {operands[0].get(), 256}; + results[0] = {srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FMOVWSr: { // fmov sd, wn - results[0] = {operands[0].get(), 256}; + results[0] = {srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FMOVXDHighr: { // fmov vd.d[1], xn - double out[2] = {operands[0].get(), operands[1].get()}; + double out[2] = {srcRegVals[0].get(), + srcRegVals[1].get()}; results[0] = {out, 256}; break; } case Opcode::AArch64_FMOVXDr: { // fmov dd, xn - results[0] = {operands[0].get(), 256}; + results[0] = {srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FMOVv2f32_ns: { // fmov vd.2s, #imm @@ -1986,321 +2013,325 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMSB_ZPmZZ_D: { // fmsb zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveFmsbPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmsbPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMSB_ZPmZZ_S: { // fmsb zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveFmsbPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveFmsbPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMSUBDrrr: { // fmsub dn, dm, da - results[0] = {multiplyHelp::msub_4ops(operands), 256}; + results[0] = {multiplyHelp::msub_4ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMSUBSrrr: { // fmsub sn, sm, sa - results[0] = {multiplyHelp::msub_4ops(operands), 256}; + results[0] = {multiplyHelp::msub_4ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMULDrr: { // fmul dd, dn, dm - results[0] = {multiplyHelp::mul_3ops(operands), 256}; + results[0] = {multiplyHelp::mul_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMULSrr: { // fmul sd, sn, sm - results[0] = {multiplyHelp::mul_3ops(operands), 256}; + results[0] = {multiplyHelp::mul_3ops(srcRegVals), 256}; break; } case Opcode::AArch64_FMUL_ZPmI_D: { // fmul zd.d, pg/m, zn.d, #imm - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, true); break; } case Opcode::AArch64_FMUL_ZPmI_S: { // fmul zd.s, pg/m, zn.s, #imm - results[0] = - sveHelp::sveMulPredicated(operands, metadata, VL_bits, true); + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + VL_bits, true); break; } case Opcode::AArch64_FMUL_ZPmZ_D: { // fmul zdn.d, pg/m, zdn.d, zm.d - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_FMUL_ZPmZ_S: { // fmul zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_FMUL_ZZZ_D: { // fmul zd.d, zn.d, zm.d - results[0] = sveHelp::sveFmul_3ops(operands, VL_bits); + results[0] = sveHelp::sveFmul_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMUL_ZZZ_S: { // fmul zd.s, zn.s, zm.s - results[0] = sveHelp::sveFmul_3ops(operands, VL_bits); + results[0] = sveHelp::sveFmul_3ops(srcRegVals, VL_bits); break; } case Opcode::AArch64_FMULv1i32_indexed: { // fmul sd, sn, vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(operands, metadata); + neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMULv1i64_indexed: { // fmul dd, dn, vm.d[index] results[0] = - neonHelp::vecFmulIndexed_vecs(operands, metadata); + neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMULv2f32: { // fmul vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](float x, float y) -> float { return x * y; }); + srcRegVals, [](float x, float y) -> float { return x * y; }); break; } case Opcode::AArch64_FMULv2f64: { // fmul vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return x * y; }); + srcRegVals, [](double x, double y) -> double { return x * y; }); break; } case Opcode::AArch64_FMULv2i32_indexed: { // fmul vd.2s, vn.2s, // vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(operands, metadata); + neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMULv2i64_indexed: { // fmul vd.2d, vn.2d, // vm.d[index] results[0] = - neonHelp::vecFmulIndexed_vecs(operands, metadata); + neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FMULv4f32: { // fmul vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](float x, float y) -> float { return x * y; }); + srcRegVals, [](float x, float y) -> float { return x * y; }); break; } case Opcode::AArch64_FMULv4i32_indexed: { // fmul vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(operands, metadata); + neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); break; } case Opcode::AArch64_FNEGDr: { // fneg dd, dn - results[0] = {-operands[0].get(), 256}; + results[0] = {-srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FNEGSr: { // fneg sd, sn - results[0] = {-operands[0].get(), 256}; + results[0] = {-srcRegVals[0].get(), 256}; break; } case Opcode::AArch64_FNEG_ZPmZ_D: { // fneg zd.d, pg/m, zn.d - results[0] = sveHelp::sveFnegPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnegPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNEG_ZPmZ_S: { // fneg zd.s, pg/m, zn.s - results[0] = sveHelp::sveFnegPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnegPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNEGv2f64: { // fneg vd.2d, vn.2d - results[0] = neonHelp::vecFneg_2ops(operands); + results[0] = neonHelp::vecFneg_2ops(srcRegVals); break; } case Opcode::AArch64_FNEGv4f32: { // fneg vd.4s, vn.4s - results[0] = neonHelp::vecFneg_2ops(operands); + results[0] = neonHelp::vecFneg_2ops(srcRegVals); break; } case Opcode::AArch64_FNMADDDrrr: { // fnmadd dd, dn, dm, da - results[0] = floatHelp::fnmadd_4ops(operands); + results[0] = floatHelp::fnmadd_4ops(srcRegVals); break; } case Opcode::AArch64_FNMADDSrrr: { // fnmadd sd, sn, sm, sa - results[0] = floatHelp::fnmadd_4ops(operands); + results[0] = floatHelp::fnmadd_4ops(srcRegVals); break; } case Opcode::AArch64_FNMLS_ZPmZZ_D: { // fnmls zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveFnmlsPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnmlsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNMLS_ZPmZZ_S: { // fnmls zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveFnmlsPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnmlsPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNMSB_ZPmZZ_D: { // fnmsb zdn.d, pg/m, zm.d, za.d - results[0] = sveHelp::sveFnmsbPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnmsbPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNMSB_ZPmZZ_S: { // fnmsb zdn.s, pg/m, zm.s, za.s - results[0] = sveHelp::sveFnmsbPredicated(operands, VL_bits); + results[0] = sveHelp::sveFnmsbPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FNMSUBDrrr: { // fnmsub dd, dn, dm, da - results[0] = floatHelp::fnmsub_4ops(operands); + results[0] = floatHelp::fnmsub_4ops(srcRegVals); break; } case Opcode::AArch64_FNMSUBSrrr: { // fnmsub sd, sn, sm, sa - results[0] = floatHelp::fnmsub_4ops(operands); + results[0] = floatHelp::fnmsub_4ops(srcRegVals); break; } case Opcode::AArch64_FNMULDrr: { // fnmul dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return -(x * y); }); + srcRegVals, [](double x, double y) -> double { return -(x * y); }); break; } case Opcode::AArch64_FNMULSrr: { // fnmul sd, sn, sm results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](float x, float y) -> float { return -(x * y); }); + srcRegVals, [](float x, float y) -> float { return -(x * y); }); break; } case Opcode::AArch64_FRINTADr: { // frinta dd, dn - results[0] = {round(operands[0].get()), 256}; + results[0] = {round(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_FRINTN_ZPmZ_D: { // frintn zd.d, pg/m, zn.d results[0] = - sveHelp::sveFrintnPredicated(operands, VL_bits); + sveHelp::sveFrintnPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FRINTN_ZPmZ_S: { // frintn zd.s, pg/m, zn.s results[0] = - sveHelp::sveFrintnPredicated(operands, VL_bits); + sveHelp::sveFrintnPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_FRINTPDr: { // frintp dd, dn - results[0] = floatHelp::frintpScalar_2ops(operands); + results[0] = floatHelp::frintpScalar_2ops(srcRegVals); break; } case Opcode::AArch64_FRINTPSr: { // frintp sd, sn - results[0] = floatHelp::frintpScalar_2ops(operands); + results[0] = floatHelp::frintpScalar_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTEv1i32: { // frsqrte sd, sn - results[0] = neonHelp::vecFrsqrte_2ops(operands); + results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTEv1i64: { // frsqrte dd, dn - results[0] = neonHelp::vecFrsqrte_2ops(operands); + results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTEv2f32: { // frsqrte vd.2s, vn.2s - results[0] = neonHelp::vecFrsqrte_2ops(operands); + results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTEv2f64: { // frsqrte vd.2d, vn.2d - results[0] = neonHelp::vecFrsqrte_2ops(operands); + results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTEv4f32: { // frsqrte vd.4s, vn.4s - results[0] = neonHelp::vecFrsqrte_2ops(operands); + results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTS32: { // frsqrts sd, sn, sm - results[0] = neonHelp::vecFrsqrts_3ops(operands); + results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTS64: { // frsqrts dd, dn, dm - results[0] = neonHelp::vecFrsqrts_3ops(operands); + results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTSv2f32: { // frsqrts vd.2s, vn.2s, vn.2s - results[0] = neonHelp::vecFrsqrts_3ops(operands); + results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTSv2f64: { // frsqrts vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFrsqrts_3ops(operands); + results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); break; } case Opcode::AArch64_FRSQRTSv4f32: { // frsqrts vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFrsqrts_3ops(operands); + results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); break; } case Opcode::AArch64_FSQRTDr: { // fsqrt dd, dn - results[0] = {::sqrt(operands[0].get()), 256}; + results[0] = {::sqrt(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_FSQRTSr: { // fsqrt sd, sn - results[0] = {::sqrtf(operands[0].get()), 256}; + results[0] = {::sqrtf(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_FSQRT_ZPmZ_D: { // fsqrt zd.d, pg/m, zn.d results[0] = - sveHelp::sveFsqrtPredicated_2vecs(operands, VL_bits); + sveHelp::sveFsqrtPredicated_2vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSQRT_ZPmZ_S: { // fsqrt zd.s, pg/m, zn.s results[0] = - sveHelp::sveFsqrtPredicated_2vecs(operands, VL_bits); + sveHelp::sveFsqrtPredicated_2vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSQRTv2f64: { // fsqrt vd.2d, vn.2d - results[0] = neonHelp::vecFsqrt_2ops(operands); + results[0] = neonHelp::vecFsqrt_2ops(srcRegVals); break; } case Opcode::AArch64_FSQRTv4f32: { // fsqrt vd.4s, vn.4s - results[0] = neonHelp::vecFsqrt_2ops(operands); + results[0] = neonHelp::vecFsqrt_2ops(srcRegVals); break; } case Opcode::AArch64_FSUBDrr: { // fsub dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return x - y; }); + srcRegVals, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUBR_ZPmZ_D: { // fsubr zdn.d, pg/m, zdn.d, zm.d results[0] = - sveHelp::sveSubrPredicated_3vecs(operands, VL_bits); + sveHelp::sveSubrPredicated_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSUBR_ZPmZ_S: { // fsubr zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveSubrPredicated_3vecs(operands, VL_bits); + results[0] = + sveHelp::sveSubrPredicated_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSUBSrr: { // fsub ss, sn, sm results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return x - y; }); + srcRegVals, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUB_ZPmI_D: { // fsub zdn.d, pg/m, zdn.d, #imm - results[0] = - sveHelp::sveSubPredicated_imm(operands, metadata, VL_bits); + results[0] = sveHelp::sveSubPredicated_imm(srcRegVals, metadata, + VL_bits); break; } case Opcode::AArch64_FSUB_ZPmI_S: { // fsub zdn.s, pg/m, zdn.s, #imm results[0] = - sveHelp::sveSubPredicated_imm(operands, metadata, VL_bits); + sveHelp::sveSubPredicated_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_FSUB_ZPmZ_D: { // fsub zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUB_ZPmZ_S: { // fsub zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, [](float x, float y) -> float { return x - y; }); + srcRegVals, VL_bits, + [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_FSUB_ZZZ_D: { // fsub zd.d, zn.d, zm.d - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSUB_ZZZ_S: { // fsub zd.s, zn.s, zm.s - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_FSUBv2f32: { results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](float x, float y) -> float { return x - y; }); + srcRegVals, [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_FSUBv2f64: { // fsub vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](double x, double y) -> double { return x - y; }); + srcRegVals, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUBv4f32: { // fsub vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](float x, float y) -> float { return x - y; }); + srcRegVals, [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, // #imm}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; @@ -2321,7 +2352,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, // zm.d, LSL #3] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -2341,7 +2372,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, [zn.d{, // #imm}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; int64_t out[32] = {0}; @@ -2359,7 +2390,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, // [, zm.d, lsl #2] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; @@ -2377,7 +2408,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, // [, zm.s, sxtw] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; @@ -2398,158 +2429,161 @@ void Instruction::execute() { } case Opcode::AArch64_INCB_XPiI: { // incb xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(operands, metadata, VL_bits); + sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCD_XPiI: { // incd xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(operands, metadata, VL_bits); + sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCD_ZPiI: { // incd zdn.d{, pattern{, #imm}} - results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCH_XPiI: { // inch xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(operands, metadata, VL_bits); + sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCH_ZPiI: { // inch zdn.h{, pattern{, #imm}} - results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCP_XP_B: { // incp xdn, pm.b - results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); + results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); break; } case Opcode::AArch64_INCP_XP_D: { // incp xdn, pm.d - results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); + results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); break; } case Opcode::AArch64_INCP_XP_H: { // incp xdn, pm.h - results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); + results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); break; } case Opcode::AArch64_INCP_XP_S: { // incp xdn, pm.s - results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); + results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); break; } case Opcode::AArch64_INCW_XPiI: { // incw xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(operands, metadata, VL_bits); + sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INCW_ZPiI: { // incw zdn.s{, pattern{, #imm}} - results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_INDEX_II_B: { // index zd.b, #imm, #imm - results[0] = - sveHelp::sveIndex(operands, metadata, VL_bits, true, true); + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, + true, true); break; } case Opcode::AArch64_INDEX_II_D: { // index zd.d, #imm, #imm - results[0] = - sveHelp::sveIndex(operands, metadata, VL_bits, true, true); + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, + true, true); break; } case Opcode::AArch64_INDEX_II_H: { // index zd.h, #imm, #imm - results[0] = - sveHelp::sveIndex(operands, metadata, VL_bits, true, true); + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, + true, true); break; } case Opcode::AArch64_INDEX_II_S: { // index zd.s, #imm, #imm - results[0] = - sveHelp::sveIndex(operands, metadata, VL_bits, true, true); + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, + true, true); break; } case Opcode::AArch64_INDEX_IR_B: { // index zd.b, #imm, wn - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_D: { // index zd.d, #imm, xn - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_H: { // index zd.h, #imm, wn - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_S: { // index zd.s, #imm, wn - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_RI_B: { // index zd.b, wn, #imm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_D: { // index zd.d, xn, #imm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_H: { // index zd.h, wn, #imm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_S: { // index zd.s, wn, #imm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RR_B: { // index zd.b, wn, wm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_D: { // index zd.d, xn, xm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_H: { // index zd.h, wn, wm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_S: { // index zd.s, wn, wm - results[0] = sveHelp::sveIndex(operands, metadata, + results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INSvi16gpr: { // ins vd.h[index], wn - results[0] = neonHelp::vecInsIndex_gpr(operands, - metadata); + results[0] = neonHelp::vecInsIndex_gpr( + srcRegVals, metadata); break; } case Opcode::AArch64_INSvi32gpr: { // ins vd.s[index], wn - results[0] = neonHelp::vecInsIndex_gpr(operands, - metadata); + results[0] = neonHelp::vecInsIndex_gpr( + srcRegVals, metadata); break; } case Opcode::AArch64_INSvi32lane: { // ins vd.s[index1], vn.s[index2] - results[0] = neonHelp::vecIns_2Index(operands, metadata); + results[0] = neonHelp::vecIns_2Index(srcRegVals, metadata); break; } case Opcode::AArch64_INSvi64gpr: { // ins vd.d[index], xn - results[0] = neonHelp::vecInsIndex_gpr(operands, - metadata); + results[0] = neonHelp::vecInsIndex_gpr( + srcRegVals, metadata); break; } case Opcode::AArch64_INSvi64lane: { // ins vd.d[index1], vn.d[index2] - results[0] = neonHelp::vecIns_2Index(operands, metadata); + results[0] = neonHelp::vecIns_2Index(srcRegVals, metadata); break; } case Opcode::AArch64_INSvi8gpr: { // ins vd.b[index], wn - results[0] = neonHelp::vecInsIndex_gpr(operands, - metadata); + results[0] = neonHelp::vecInsIndex_gpr( + srcRegVals, metadata); break; } case Opcode::AArch64_LD1_MXIPXX_H_D: { // ld1d {zath.d[ws, #imm]}, pg/z, @@ -2559,9 +2593,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2584,7 +2618,7 @@ void Instruction::execute() { results[i] = {out, 256}; else // Maintain un-updated rows. - results[i] = operands[i]; + results[i] = srcRegVals[i]; } break; } @@ -2595,9 +2629,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2605,7 +2639,7 @@ void Instruction::execute() { for (int i = 0; i < partition_num; i++) { uint64_t* row = - const_cast(operands[i].getAsVector()); + const_cast(srcRegVals[i].getAsVector()); uint64_t shifted_active = 1ull << ((i % 8) * 8); if (pg[i / 8] & shifted_active) { row[sliceNum] = data[i]; @@ -2623,9 +2657,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2648,7 +2682,7 @@ void Instruction::execute() { results[i] = {out, 256}; else // Maintain un-updated rows. - results[i] = operands[i]; + results[i] = srcRegVals[i]; } break; } @@ -2659,9 +2693,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2669,7 +2703,7 @@ void Instruction::execute() { for (int i = 0; i < partition_num; i++) { uint32_t* row = - const_cast(operands[i].getAsVector()); + const_cast(srcRegVals[i].getAsVector()); uint64_t shifted_active = 1ull << ((i % 16) * 4); if (pg[i / 16] & shifted_active) { row[sliceNum] = data[i]; @@ -2682,7 +2716,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1B: { // ld1b {zt.b}, pg/z, [xn, xm] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 8; const uint8_t* data = memoryData[0].getAsVector(); @@ -2702,7 +2736,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 8; const uint8_t* data = memoryData[0].getAsVector(); @@ -2720,7 +2754,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1D: { // ld1d {zt.d}, pg/z, [xn, xm, lsl #3] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; const uint64_t* data = memoryData[0].getAsVector(); @@ -2740,7 +2774,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1D_IMM_REAL: { // ld1d {zt.d}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; const uint64_t* data = memoryData[0].getAsVector(); @@ -2759,7 +2793,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1H: { // ld1h {zt.h}, pg/z, [xn, xm, lsl #1] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 16; const uint16_t* data = memoryData[0].getAsVector(); @@ -2785,9 +2819,9 @@ void Instruction::execute() { // if #imm post-index, value can only be 16 const uint64_t postIndex = (metadata.operands[2].type == ARM64_OP_REG) - ? operands[1].get() + ? srcRegVals[1].get() : 16; - results[1] = operands[0].get() + postIndex; + results[1] = srcRegVals[0].get() + postIndex; break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] @@ -2797,7 +2831,7 @@ void Instruction::execute() { uint16_t index = 0; // Check if any lanes are active, otherwise set all to 0 and break early bool active = false; - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { active = true; @@ -2819,7 +2853,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_D_IMM: { // ld1rqd {zd.d}, pg/z, [xn{, #imm}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; const uint64_t* data = memoryData[0].getAsVector(); @@ -2843,7 +2877,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_W: { // ld1rqw {zd.s}, pg/z, [xn, xm, lsl #2] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; const uint32_t* data = memoryData[0].getAsVector(); @@ -2869,7 +2903,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_W_IMM: { // ld1rqw {zd.s}, pg/z, [xn{, #imm}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; const uint32_t* data = memoryData[0].getAsVector(); @@ -2900,7 +2934,7 @@ void Instruction::execute() { // Check if any lanes are active, otherwise set all to 0 and break early bool active = false; - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { active = true; @@ -2931,7 +2965,7 @@ void Instruction::execute() { uint8_t out[16] = {val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv1d: { // ld1r {vt.1d}, [xn] @@ -2946,7 +2980,7 @@ void Instruction::execute() { uint64_t val = memoryData[0].get(); uint64_t out[2] = {val, 0}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv2d: { // ld1r {vt.2d}, [xn] @@ -2961,7 +2995,7 @@ void Instruction::execute() { uint64_t val = memoryData[0].get(); uint64_t out[2] = {val, val}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv2s: { // ld1r {vt.2s}, [xn] @@ -2976,7 +3010,7 @@ void Instruction::execute() { uint32_t val = memoryData[0].get(); uint32_t out[4] = {val, val, 0, 0}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv4h: { // ld1r {vt.4h}, [xn] @@ -2991,7 +3025,7 @@ void Instruction::execute() { uint16_t val = memoryData[0].get(); uint16_t out[8] = {val, val, val, val, 0, 0, 0, 0}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv4s: { // ld1r {vt.4s}, [xn] @@ -3006,7 +3040,7 @@ void Instruction::execute() { uint32_t val = memoryData[0].get(); uint32_t out[4] = {val, val, val, val}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv8b: { // ld1r {vt.8b}, [xn] @@ -3023,7 +3057,7 @@ void Instruction::execute() { uint8_t out[16] = {val, val, val, val, val, val, val, val, 0, 0, 0, 0, 0, 0, 0, 0}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv8h: { // ld1r {vt.8h}, [xn] @@ -3038,7 +3072,7 @@ void Instruction::execute() { uint16_t val = memoryData[0].get(); uint16_t out[8] = {val, val, val, val, val, val, val, val}; results[0] = {out, 256}; - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Fourv16b: // ld1 {vt1.16b, vt2.16b, vt3.16b, @@ -3071,9 +3105,9 @@ void Instruction::execute() { results[3] = memoryData[3].zeroExtend(memoryData[3].size(), 256); // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? operands[1].get() + ? srcRegVals[1].get() : 64; - results[4] = operands[0].get() + postIndex; + results[4] = srcRegVals[0].get() + postIndex; break; } case Opcode::AArch64_LD1Twov16b: // ld1 {vt1.16b, vt2.16b}, [xn] @@ -3100,14 +3134,14 @@ void Instruction::execute() { // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? operands[1].get() + ? srcRegVals[1].get() : 32; - results[2] = operands[0].get() + postIndex; + results[2] = srcRegVals[0].get() + postIndex; break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; const uint32_t* data = memoryData[0].getAsVector(); @@ -3127,7 +3161,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1W_IMM_REAL: { // ld1w {zt.s}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; const uint32_t* data = memoryData[0].getAsVector(); @@ -3147,7 +3181,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1i32: { // ld1 {vt.s}[index], [xn] // LOAD const int index = metadata.operands[0].vector_index; - const uint32_t* vt = operands[0].getAsVector(); + const uint32_t* vt = srcRegVals[0].getAsVector(); uint32_t out[4]; for (int i = 0; i < 4; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; @@ -3158,7 +3192,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1i64: { // ld1 {vt.d}[index], [xn] // LOAD const int index = metadata.operands[0].vector_index; - const uint64_t* vt = operands[0].getAsVector(); + const uint64_t* vt = srcRegVals[0].getAsVector(); uint64_t out[2]; for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; @@ -3169,13 +3203,13 @@ void Instruction::execute() { case Opcode::AArch64_LD1i64_POST: { // ld1 {vt.d}[index], [xn], #8 // LOAD const int index = metadata.operands[0].vector_index; - const uint64_t* vt = operands[0].getAsVector(); + const uint64_t* vt = srcRegVals[0].getAsVector(); uint64_t out[2]; for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; } results[0] = {out, 256}; - results[1] = operands[1].get() + metadata.operands[2].imm; + results[1] = srcRegVals[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD2D: // ld2d {zt1.d, zt2.d}, pg/z, [, xm, @@ -3183,7 +3217,7 @@ void Instruction::execute() { case Opcode::AArch64_LD2D_IMM: { // ld2d {zt1.d, zt2.d}, pg/z, [{, // #imm, mul vl}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3227,15 +3261,15 @@ void Instruction::execute() { results[1] = {t2, 256}; uint64_t offset = 32; if (metadata.operandCount == 4) { - offset = operands[3].get(); + offset = srcRegVals[3].get(); } - results[2] = operands[2].get() + offset; + results[2] = srcRegVals[2].get() + offset; break; } case Opcode::AArch64_LD3D_IMM: { // ld3d {zt1.d, zt2.d, zt3.d}, pg/z, // [xn|sp{, #imm, MUL VL}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3261,7 +3295,7 @@ void Instruction::execute() { case Opcode::AArch64_LD4D_IMM: { // ld4d {zt1.d, zt2.d, zt3.d, zt4.d}, // pg/z, [xn|sp{, #imm, MUL VL}] // LOAD - const uint64_t* p = operands[0].getAsVector(); + const uint64_t* p = srcRegVals[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3292,7 +3326,7 @@ void Instruction::execute() { // LOAD results[0] = memoryData[0].zeroExtend(4, 8); memoryData[0] = RegisterValue( - memoryData[0].get() + operands[0].get(), 4); + memoryData[0].get() + srcRegVals[0].get(), 4); break; } case Opcode::AArch64_LDARB: { // ldarb wt, [xn] @@ -3346,7 +3380,7 @@ void Instruction::execute() { (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = memoryData[1].zeroExtend(dataSize_, regSize); - results[2] = operands[0].get() + metadata.operands[3].imm; + results[2] = srcRegVals[0].get() + metadata.operands[3].imm; break; } case Opcode::AArch64_LDPDpre: // ldp dt1, dt2, [xn, #imm]! @@ -3359,7 +3393,7 @@ void Instruction::execute() { results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = memoryData[1].zeroExtend(dataSize_, regSize); results[2] = - operands[0].get() + metadata.operands[2].mem.disp; + srcRegVals[0].get() + metadata.operands[2].mem.disp; break; } case Opcode::AArch64_LDPSWi: { // ldpsw xt1, xt2, [xn {, #imm}] @@ -3371,14 +3405,14 @@ void Instruction::execute() { case Opcode::AArch64_LDRBBpost: { // ldrb wt, [xn], #imm // LOAD results[0] = memoryData[0].zeroExtend(1, 8); - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRBBpre: { // ldrb wt, [xn, #imm]! // LOAD results[0] = memoryData[0].zeroExtend(1, 8); results[1] = - operands[0].get() + metadata.operands[1].mem.disp; + srcRegVals[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRBBroW: { // ldrb wt, @@ -3420,7 +3454,7 @@ void Instruction::execute() { uint16_t regSize = (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRBpre: // ldr bt, [xn, #imm]! @@ -3434,7 +3468,7 @@ void Instruction::execute() { (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = - operands[0].get() + metadata.operands[1].mem.disp; + srcRegVals[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRDroW: { // ldr dt, [xn, wm, {extend {#amount}}] @@ -3450,14 +3484,14 @@ void Instruction::execute() { case Opcode::AArch64_LDRHHpost: { // ldrh wt, [xn], #imm // LOAD results[0] = memoryData[0].zeroExtend(2, 8); - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRHHpre: { // ldrh wt, [xn, #imm]! // LOAD results[0] = memoryData[0].zeroExtend(2, 8); results[1] = - operands[0].get() + metadata.operands[1].mem.disp; + srcRegVals[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRHHroW: { // ldrh wt, [xn, wm, {extend {#amount}}] @@ -3548,7 +3582,7 @@ void Instruction::execute() { case Opcode::AArch64_LDRSWpost: { // ldrsw xt, [xn], #simm // LOAD results[0] = static_cast(memoryData[0].get()); - results[1] = operands[0].get() + metadata.operands[2].imm; + results[1] = srcRegVals[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRSWroX: { // ldrsw xt, [xn, xm{, extend @@ -3683,52 +3717,55 @@ void Instruction::execute() { } case Opcode::AArch64_LSLVWr: { // lslv wd, wn, wm results[0] = { - logicalHelp::logicalShiftLR_3ops(operands, true), 8}; + logicalHelp::logicalShiftLR_3ops(srcRegVals, true), 8}; break; } case Opcode::AArch64_LSLVXr: { // lslv xd, xn, xm - results[0] = logicalHelp::logicalShiftLR_3ops(operands, true); + results[0] = + logicalHelp::logicalShiftLR_3ops(srcRegVals, true); break; } case Opcode::AArch64_LSL_ZZI_S: { // lsl zd.s, zn.s, #imm - results[0] = sveHelp::sveLsl_imm(operands, metadata, VL_bits); + results[0] = + sveHelp::sveLsl_imm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_LSRVWr: { // lsrv wd, wn, wm results[0] = { - logicalHelp::logicalShiftLR_3ops(operands, false), 8}; + logicalHelp::logicalShiftLR_3ops(srcRegVals, false), 8}; break; } case Opcode::AArch64_LSRVXr: { // lsrv xd, xn, xm results[0] = - logicalHelp::logicalShiftLR_3ops(operands, false); + logicalHelp::logicalShiftLR_3ops(srcRegVals, false); break; } case Opcode::AArch64_MADDWrrr: { // madd wd, wn, wm, wa - results[0] = {multiplyHelp::madd_4ops(operands), 8}; + results[0] = {multiplyHelp::madd_4ops(srcRegVals), 8}; break; } case Opcode::AArch64_MADDXrrr: { // madd xd, xn, xm, xa - results[0] = multiplyHelp::madd_4ops(operands); + results[0] = multiplyHelp::madd_4ops(srcRegVals); break; } case Opcode::AArch64_MLA_ZPmZZ_B: { // mla zda.b, pg/m, zn.b, zm.b - results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_D: { // mla zda.d, pg/m, zn.d, zm.d results[0] = - sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_H: { // mla zda.h, pg/m, zn.h, zm.h results[0] = - sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_S: { // mla zda.s, pg/m, zn.s, zm.s results[0] = - sveHelp::sveMlaPredicated_vecs(operands, VL_bits); + sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_MOVID: { // movi dd, #imm @@ -3757,12 +3794,12 @@ void Instruction::execute() { } case Opcode::AArch64_MOVKWi: { // movk wd, #imm results[0] = { - arithmeticHelp::movkShift_imm(operands, metadata), 8}; + arithmeticHelp::movkShift_imm(srcRegVals, metadata), 8}; break; } case Opcode::AArch64_MOVKXi: { // movk xd, #imm results[0] = - arithmeticHelp::movkShift_imm(operands, metadata); + arithmeticHelp::movkShift_imm(srcRegVals, metadata); break; } case Opcode::AArch64_MOVNWi: { // movn wd, #imm{, LSL #shift} @@ -3778,22 +3815,22 @@ void Instruction::execute() { } case Opcode::AArch64_MOVPRFX_ZPmZ_D: { // movprfx zd.d, pg/m, zn.d results[0] = sveHelp::sveMovprfxPredicated_destUnchanged( - operands, VL_bits); + srcRegVals, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZPzZ_D: { // movprfx zd.d, pg/z, zn.d results[0] = sveHelp::sveMovprfxPredicated_destToZero( - operands, VL_bits); + srcRegVals, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZPzZ_S: { // movprfx zd.s, pg/z, zn.s results[0] = sveHelp::sveMovprfxPredicated_destToZero( - operands, VL_bits); + srcRegVals, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZZ: { // movprfx zd, zn // TODO: Adopt hint logic of the MOVPRFX instruction - results[0] = operands[0]; + results[0] = srcRegVals[0]; break; } case Opcode::AArch64_MOVZWi: { // movz wd, #imm @@ -3808,7 +3845,7 @@ void Instruction::execute() { break; } case Opcode::AArch64_MRS: { // mrs xt, (systemreg|Sop0_op1_Cn_Cm_op2) - results[0] = operands[0]; + results[0] = srcRegVals[0]; break; } case Opcode::AArch64_MSR: { // msr (systemreg|Sop0_op1_Cn_Cm_op2), xt @@ -3818,16 +3855,16 @@ void Instruction::execute() { static_cast(ARM64_SYSREG_SVCR)) { return SMZAupdated(); } else { - results[0] = operands[0]; + results[0] = srcRegVals[0]; } break; } case Opcode::AArch64_MSUBWrrr: { // msub wd, wn, wm, wa - results[0] = {multiplyHelp::msub_4ops(operands), 8}; + results[0] = {multiplyHelp::msub_4ops(srcRegVals), 8}; break; } case Opcode::AArch64_MSUBXrrr: { // msub xd, xn, xm, xa - results[0] = multiplyHelp::msub_4ops(operands); + results[0] = multiplyHelp::msub_4ops(srcRegVals); break; } case Opcode::AArch64_MSRpstatesvcrImm1: { // msr svcr, #imm @@ -3850,22 +3887,22 @@ void Instruction::execute() { } } case Opcode::AArch64_MUL_ZPmZ_B: { // mul zdn.b, pg/m, zdn.b, zm.b - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_D: { // mul zdn.d, pg/m, zdn.d, zm.d - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_H: { // mul zdn.h, pg/m, zdn.h, zm.h - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_S: { // mul zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveMulPredicated(operands, metadata, + results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, VL_bits, false); break; } @@ -3894,75 +3931,75 @@ void Instruction::execute() { break; } case Opcode::AArch64_NEGv2i64: { // neg vd.2d, vn.2d - results[0] = neonHelp::vecFneg_2ops(operands); + results[0] = neonHelp::vecFneg_2ops(srcRegVals); break; } case Opcode::AArch64_NOTv16i8: { // not vd.16b, vn.16b results[0] = neonHelp::vecLogicOp_2vecs( - operands, [](uint8_t x) -> uint8_t { return ~x; }); + srcRegVals, [](uint8_t x) -> uint8_t { return ~x; }); break; } case Opcode::AArch64_NOTv8i8: { // not vd.8b, vn.8b results[0] = neonHelp::vecLogicOp_2vecs( - operands, [](uint8_t x) -> uint8_t { return ~x; }); + srcRegVals, [](uint8_t x) -> uint8_t { return ~x; }); break; } case Opcode::AArch64_ORNWrs: { // orn wd, wn, wm{, shift{ #amount}} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | (~y); }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORNXrs: { // orn xd, xn, xm{, shift{ #amount}} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | (~y); }); results[0] = result; break; } case Opcode::AArch64_ORRWri: { // orr wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORRWrs: { // orr wd, wn, wm{, shift{ #amount}} results[0] = { - comparisonHelp::orrShift_3ops(operands, metadata), 8}; + comparisonHelp::orrShift_3ops(srcRegVals, metadata), 8}; break; } case Opcode::AArch64_ORRXri: { // orr xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - operands, metadata, false, + srcRegVals, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORRXrs: { // orr xd, xn, xm{, shift{ #amount}} results[0] = - comparisonHelp::orrShift_3ops(operands, metadata); + comparisonHelp::orrShift_3ops(srcRegVals, metadata); break; } case Opcode::AArch64_ORR_PPzPP: { // orr pd.b, pg/z, pn.b, pm.b results[0] = sveHelp::sveLogicOp_preds( - operands, VL_bits, + srcRegVals, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x | y; }); break; } case Opcode::AArch64_ORR_ZZZ: { // orr zd.d, zn.d, zm.d - results[0] = sveHelp::sveOrr_3vecs(operands, VL_bits); + results[0] = sveHelp::sveOrr_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_ORRv16i8: { // orr vd.16b, Vn.16b, Vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); break; } case Opcode::AArch64_ORRv8i8: { // orr vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); break; } case Opcode::AArch64_PFALSE: { // pfalse pd.b @@ -3974,24 +4011,24 @@ void Instruction::execute() { break; } case Opcode::AArch64_PSEL_PPPRI_B: { // psel pd, pn, pm.b[wa, #imm] - results[0] = sveHelp::svePsel(operands, metadata, VL_bits); + results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_D: { // psel pd, pn, pm.d[wa, #imm] - results[0] = sveHelp::svePsel(operands, metadata, VL_bits); + results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_H: { // psel pd, pn, pm.h[wa, #imm] - results[0] = sveHelp::svePsel(operands, metadata, VL_bits); + results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_S: { // psel pd, pn, pm.s[wa, #imm] - results[0] = sveHelp::svePsel(operands, metadata, VL_bits); + results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_PTEST_PP: { // ptest pg, pn.b - const uint64_t* g = operands[0].getAsVector(); - const uint64_t* s = operands[1].getAsVector(); + const uint64_t* g = srcRegVals[0].getAsVector(); + const uint64_t* s = srcRegVals[1].getAsVector(); std::array masked_n = {(g[0] & s[0]), (g[1] & s[1]), (g[2] & s[2]), (g[3] & s[3])}; // Byte count = 1 as destination predicate is regarding single bytes. @@ -4015,19 +4052,19 @@ void Instruction::execute() { break; } case Opcode::AArch64_PUNPKHI_PP: { // punpkhi pd.h, pn.b - results[0] = sveHelp::svePunpk(operands, VL_bits, true); + results[0] = sveHelp::svePunpk(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_PUNPKLO_PP: { // punpklo pd.h, pn.b - results[0] = sveHelp::svePunpk(operands, VL_bits, false); + results[0] = sveHelp::svePunpk(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_RBITWr: { // rbit wd, wn - results[0] = {bitmanipHelp::rbit(operands, metadata), 8}; + results[0] = {bitmanipHelp::rbit(srcRegVals, metadata), 8}; break; } case Opcode::AArch64_RBITXr: { // rbit xd, xn - results[0] = bitmanipHelp::rbit(operands, metadata); + results[0] = bitmanipHelp::rbit(srcRegVals, metadata); break; } case Opcode::AArch64_RDVLI_XI: { // rdvl xd, #imm @@ -4037,308 +4074,312 @@ void Instruction::execute() { } case Opcode::AArch64_RET: { // ret {xr} branchTaken_ = true; - branchAddress_ = operands[0].get(); + branchAddress_ = srcRegVals[0].get(); break; } case Opcode::AArch64_REV16v16i8: { // rev16 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV16v8i8: { // rev16 Vd.8b, Vn.8b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV32v16i8: { // rev32 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV32v4i16: { // rev32 Vd.4h, Vn.4h - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV32v8i16: { // rev32 Vd.8h, Vn.8h - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV32v8i8: { // rev32 Vd.8b, Vn.8b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v16i8: { // rev64 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v2i32: { // rev64 Vd.2s, Vn.2s - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v4i16: { // rev64 Vd.4h, Vn.4h - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v4i32: { // rev64 Vd.4s, Vn.4s - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v8i16: { // rev64 Vd.8h, Vn.8h - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REV64v8i8: { // rev64 Vd.8b Vn.8b - results[0] = neonHelp::vecRev(operands); + results[0] = neonHelp::vecRev(srcRegVals); break; } case Opcode::AArch64_REVXr: { // rev xd, xn - results[0] = bitmanipHelp::rev(operands); + results[0] = bitmanipHelp::rev(srcRegVals); break; } case Opcode::AArch64_REV_PP_B: { // rev pd.b, pn.b - results[0] = sveHelp::sveRev_predicates(operands, VL_bits); + results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_PP_D: { // rev pd.d, pn.d - results[0] = sveHelp::sveRev_predicates(operands, VL_bits); + results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_PP_H: { // rev pd.h, pn.h - results[0] = sveHelp::sveRev_predicates(operands, VL_bits); + results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_PP_S: { // rev pd.s, pn.s - results[0] = sveHelp::sveRev_predicates(operands, VL_bits); + results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_ZZ_B: { // rev zd.b, zn.b - results[0] = sveHelp::sveRev_vecs(operands, VL_bits); + results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_ZZ_D: { // rev zd.d, zn.d - results[0] = sveHelp::sveRev_vecs(operands, VL_bits); + results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_ZZ_H: { // rev zd.h, zn.h - results[0] = sveHelp::sveRev_vecs(operands, VL_bits); + results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_REV_ZZ_S: { // rev zd.s, zn.s - results[0] = sveHelp::sveRev_vecs(operands, VL_bits); + results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_RORVWr: { // rorv wd, wn, wm - results[0] = {logicalHelp::rorv_3ops(operands), 8}; + results[0] = {logicalHelp::rorv_3ops(srcRegVals), 8}; break; } case Opcode::AArch64_RORVXr: { // rorv xd, xn, xm - results[0] = logicalHelp::rorv_3ops(operands); + results[0] = logicalHelp::rorv_3ops(srcRegVals); break; } case Opcode::AArch64_SBCWr: { // sbc wd, wn, wm - results[0] = {arithmeticHelp::sbc(operands), 8}; + results[0] = {arithmeticHelp::sbc(srcRegVals), 8}; break; } case Opcode::AArch64_SBCXr: { // sbc xd, xn, xm - results[0] = arithmeticHelp::sbc(operands); + results[0] = arithmeticHelp::sbc(srcRegVals); break; } case Opcode::AArch64_SBFMWri: { // sbfm wd, wn, #immr, #imms results[0] = { - bitmanipHelp::bfm_2imms(operands, metadata, true, true), + bitmanipHelp::bfm_2imms(srcRegVals, metadata, true, true), 8}; break; } case Opcode::AArch64_SBFMXri: { // sbfm xd, xn, #immr, #imms results[0] = - bitmanipHelp::bfm_2imms(operands, metadata, true, true); + bitmanipHelp::bfm_2imms(srcRegVals, metadata, true, true); break; } case Opcode::AArch64_SCVTFSWSri: { // scvtf sd, wn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(operands, metadata); + floatHelp::scvtf_FixedPoint(srcRegVals, metadata); break; } case Opcode::AArch64_SCVTFSXDri: { // scvtf dd, xn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(operands, metadata); + floatHelp::scvtf_FixedPoint(srcRegVals, metadata); break; } case Opcode::AArch64_SCVTFSXSri: { // scvtf sd, xn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(operands, metadata); + floatHelp::scvtf_FixedPoint(srcRegVals, metadata); break; } case Opcode::AArch64_SCVTFUWDri: { // scvtf dd, wn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUWSri: { // scvtf sd, wn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUXDri: { // scvtf dd, xn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUXSri: { // scvtf sd, xn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTF_ZPmZ_DtoD: { // scvtf zd.d, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_DtoS: { // scvtf zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_StoD: { // scvtf zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_StoS: { // scvtf zd.s, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(operands, VL_bits); + sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SCVTFv1i32: { // scvtf sd, sn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTFv1i64: { // scvtf dd, dn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_SCVTFv2f32: { // scvtf vd.2s, vn.2s results[0] = neonHelp::vecScvtf_2vecs( - operands, [](int32_t x) -> float { return static_cast(x); }); + srcRegVals, + [](int32_t x) -> float { return static_cast(x); }); break; } case Opcode::AArch64_SCVTFv2f64: { // scvtf vd.2d, vn.2d results[0] = neonHelp::vecScvtf_2vecs( - operands, + srcRegVals, [](int64_t x) -> double { return static_cast(x); }); break; } case Opcode::AArch64_SCVTFv4f32: { // scvtf vd.4s, vn.4s results[0] = neonHelp::vecScvtf_2vecs( - operands, [](int32_t x) -> float { return static_cast(x); }); + srcRegVals, + [](int32_t x) -> float { return static_cast(x); }); break; } case Opcode::AArch64_SDIVWr: { // sdiv wd, wn, wm - results[0] = {divideHelp::div_3ops(operands), 8}; + results[0] = {divideHelp::div_3ops(srcRegVals), 8}; break; } case Opcode::AArch64_SDIVXr: { // sdiv xd, xn, xm - results[0] = {divideHelp::div_3ops(operands), 8}; + results[0] = {divideHelp::div_3ops(srcRegVals), 8}; break; } case Opcode::AArch64_SEL_ZPZZ_D: { // sel zd.d, pg, zn.d, zm.d - results[0] = sveHelp::sveSel_zpzz(operands, VL_bits); + results[0] = sveHelp::sveSel_zpzz(srcRegVals, VL_bits); break; } case Opcode::AArch64_SEL_ZPZZ_S: { // sel zd.s, pg, zn.s, zm.s - results[0] = sveHelp::sveSel_zpzz(operands, VL_bits); + results[0] = sveHelp::sveSel_zpzz(srcRegVals, VL_bits); break; } case Opcode::AArch64_SHLd: { // shl dd, dn #imm results[0] = - neonHelp::vecShlShift_vecImm(operands, metadata); + neonHelp::vecShlShift_vecImm(srcRegVals, metadata); break; } case Opcode::AArch64_SHLv4i32_shift: { // shl vd.4s, vn.4s, #imm results[0] = - neonHelp::vecShlShift_vecImm(operands, metadata); + neonHelp::vecShlShift_vecImm(srcRegVals, metadata); break; } case Opcode::AArch64_SMADDLrrr: { // smaddl xd, wn, wm, xa - results[0] = multiplyHelp::maddl_4ops(operands); + results[0] = multiplyHelp::maddl_4ops(srcRegVals); break; } case Opcode::AArch64_SMAX_ZI_S: { // smax zdn.s, zdn.s, #imm results[0] = - sveHelp::sveMax_vecImm(operands, metadata, VL_bits); + sveHelp::sveMax_vecImm(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_SMAX_ZPmZ_S: { // smax zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveMaxPredicated_vecs(operands, VL_bits); + results[0] = + sveHelp::sveMaxPredicated_vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_SMAXv4i32: { // smax vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - operands, + srcRegVals, [](int32_t x, int32_t y) -> int32_t { return std::max(x, y); }); break; } case Opcode::AArch64_SMINV_VPZ_S: { // sminv sd, pg, zn.s - results[0] = sveHelp::sveSminv(operands, VL_bits); + results[0] = sveHelp::sveSminv(srcRegVals, VL_bits); break; } case Opcode::AArch64_SMINVv4i32v: { // sminv sd, vn.4s - results[0] = neonHelp::vecMinv_2ops(operands); + results[0] = neonHelp::vecMinv_2ops(srcRegVals); break; } case Opcode::AArch64_SMIN_ZPmZ_S: { // smin zd.s, pg/m, zn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - operands, VL_bits, + srcRegVals, VL_bits, [](int32_t x, int32_t y) -> int32_t { return std::min(x, y); }); break; } case Opcode::AArch64_SMINv4i32: { // smin vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - operands, + srcRegVals, [](int32_t x, int32_t y) -> int32_t { return std::min(x, y); }); break; } case Opcode::AArch64_SMSUBLrrr: { // smsubl xd, wn, wm, xa - results[0] = arithmeticHelp::msubl_4ops(operands); + results[0] = arithmeticHelp::msubl_4ops(srcRegVals); break; } case Opcode::AArch64_SMULH_ZPmZ_B: { // smulh zdn.b, pg/m, zdn.b, zm.b results[0] = - sveHelp::sveMulhPredicated(operands, VL_bits); + sveHelp::sveMulhPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SMULH_ZPmZ_H: { // smulh zdn.h, pg/m, zdn.h, zm.h results[0] = - sveHelp::sveMulhPredicated(operands, VL_bits); + sveHelp::sveMulhPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SMULH_ZPmZ_S: { // smulh zdn.s, pg/m, zdn.s, zm.s results[0] = - sveHelp::sveMulhPredicated(operands, VL_bits); + sveHelp::sveMulhPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SMULHrr: { // smulh xd, xn, xm // TODO: signed - results[0] = AuxFunc::mulhi(operands[0].get(), - operands[1].get()); + results[0] = AuxFunc::mulhi(srcRegVals[0].get(), + srcRegVals[1].get()); break; } case Opcode::AArch64_SSHLLv2i32_shift: { // sshll vd.2d, vn.2s, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, false); + srcRegVals, metadata, false); break; } case Opcode::AArch64_SSHLLv4i32_shift: { // sshll2 vd.2d, vn.4s, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, true); + srcRegVals, metadata, true); break; } case Opcode::AArch64_SHRNv8i8_shift: { // shrn vd.8b, vn.8h, #imm - results[0] = neonHelp::vecShrnShift_imm(operands, - metadata); + results[0] = neonHelp::vecShrnShift_imm( + srcRegVals, metadata); break; } case Opcode::AArch64_SSHRv4i32_shift: { // sshr vd.4s, vn.4s, #imm - results[0] = neonHelp::vecSshrShift_imm(operands, metadata); + results[0] = + neonHelp::vecSshrShift_imm(srcRegVals, metadata); break; } case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4353,8 +4394,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4369,8 +4410,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1D_IMM: { // st1d {zd.d}, pg, [zn.d{, #imm}] // STORE - const uint64_t* t = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4387,8 +4428,8 @@ void Instruction::execute() { // zm.d, lsl # // 3] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4408,14 +4449,15 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; - const uint64_t* tileSlice = operands[sliceNum].getAsVector(); + const uint64_t* tileSlice = + srcRegVals[sliceNum].getAsVector(); memoryData = sveHelp::sve_merge_store_data(tileSlice, pg, VL_bits); @@ -4428,9 +4470,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -4442,7 +4484,7 @@ void Instruction::execute() { for (uint16_t x = 0; x < partition_num; x++) { uint64_t shifted_active = 1ull << ((x % 8) * 8); if (pg[x / 8] & shifted_active) { - mdata[md_size] = operands[x].getAsVector()[sliceNum]; + mdata[md_size] = srcRegVals[x].getAsVector()[sliceNum]; md_size++; } else if (md_size) { memoryData[index] = RegisterValue((char*)mdata.data(), md_size * 8); @@ -4462,14 +4504,15 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; - const uint32_t* tileSlice = operands[sliceNum].getAsVector(); + const uint32_t* tileSlice = + srcRegVals[sliceNum].getAsVector(); memoryData = sveHelp::sve_merge_store_data(tileSlice, pg, VL_bits); @@ -4482,9 +4525,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = operands[partition_num].get(); + const uint32_t ws = srcRegVals[partition_num].get(); const uint64_t* pg = - operands[partition_num + 1].getAsVector(); + srcRegVals[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -4496,7 +4539,7 @@ void Instruction::execute() { for (uint16_t x = 0; x < partition_num; x++) { uint64_t shifted_active = 1ull << ((x % 16) * 4); if (pg[x / 16] & shifted_active) { - mdata[md_size] = operands[x].getAsVector()[sliceNum]; + mdata[md_size] = srcRegVals[x].getAsVector()[sliceNum]; md_size++; } else if (md_size) { memoryData[index] = RegisterValue((char*)mdata.data(), md_size * 4); @@ -4512,8 +4555,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1W_D_IMM: { // st1w {zt.d}, pg, [zn.d{, #imm}] // STORE - const uint64_t* t = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4528,8 +4571,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1W_IMM: { // st1w {zt.s}, pg, [zn.s{, #imm}] // STORE - const uint32_t* t = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint32_t* t = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint16_t index = 0; @@ -4544,32 +4587,32 @@ void Instruction::execute() { } case Opcode::AArch64_ST1B: { // st1b {zt.b}, pg, [xn, xm] // STORE - const uint8_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint8_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1B_IMM: { // st1b {zt.b}, pg, [xn{, #imm, mul vl}] // STORE - const uint8_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint8_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1D: { // st1d {zt.d}, pg, [xn, xm, lsl #3] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1D_IMM: { // st1d {zt.d}, pg, [xn{, #imm, mul vl}] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; @@ -4578,8 +4621,9 @@ void Instruction::execute() { // vt4.16b}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 16 * sizeof(uint8_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 16 * sizeof(uint8_t)); } break; } @@ -4588,22 +4632,24 @@ void Instruction::execute() { // <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 16 * sizeof(uint8_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 16 * sizeof(uint8_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? operands[5].get() + ? srcRegVals[5].get() : 64; - results[0] = operands[4].get() + postIndex; + results[0] = srcRegVals[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv2d: { // st1 {vt.2d, vt2.2d, vt3.2d, // vt4.2d}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 2 * sizeof(uint64_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 2 * sizeof(uint64_t)); } break; } @@ -4611,36 +4657,39 @@ void Instruction::execute() { // vt4.2d}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 2 * sizeof(uint64_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 2 * sizeof(uint64_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? operands[5].get() + ? srcRegVals[5].get() : 64; - results[0] = operands[4].get() + postIndex; + results[0] = srcRegVals[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv2s_POST: { // st1 {vt.2s, vt2.2s, vt3.2s, // vt4.2s}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 2 * sizeof(uint32_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 2 * sizeof(uint32_t)); } // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? operands[5].get() + ? srcRegVals[5].get() : 32; - results[0] = operands[4].get() + postIndex; + results[0] = srcRegVals[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv4s: { // st1 {vt.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 4 * sizeof(uint32_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 4 * sizeof(uint32_t)); } break; } @@ -4648,20 +4697,21 @@ void Instruction::execute() { // vt4.4s}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = RegisterValue( - (char*)operands[i].getAsVector(), 4 * sizeof(uint32_t)); + memoryData[i] = + RegisterValue((char*)srcRegVals[i].getAsVector(), + 4 * sizeof(uint32_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? operands[5].get() + ? srcRegVals[5].get() : 64; - results[0] = operands[4].get() + postIndex; + results[0] = srcRegVals[4].get() + postIndex; break; } case Opcode::AArch64_ST1Twov16b: { // st1 {vt.16b, vt2.16b}, [xn|sp] // STORE - const uint8_t* t = operands[0].getAsVector(); - const uint8_t* t2 = operands[1].getAsVector(); + const uint8_t* t = srcRegVals[0].getAsVector(); + const uint8_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 16 * sizeof(uint8_t)); memoryData[1] = RegisterValue((char*)t2, 16 * sizeof(uint8_t)); break; @@ -4669,22 +4719,22 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov16b_POST: { // st1 {vt.16b, vt2.16b}, // [xn|sp], <#imm|xm> // STORE - const uint8_t* t = operands[0].getAsVector(); - const uint8_t* t2 = operands[1].getAsVector(); + const uint8_t* t = srcRegVals[0].getAsVector(); + const uint8_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 16 * sizeof(uint8_t)); memoryData[1] = RegisterValue((char*)t2, 16 * sizeof(uint8_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? operands[3].get() + ? srcRegVals[3].get() : 32; - results[0] = operands[2].get() + postIndex; + results[0] = srcRegVals[2].get() + postIndex; break; } case Opcode::AArch64_ST1Twov2d: { // st1 {vt.2d, vt2.2d}, [xn|sp] // STORE - const uint64_t* t = operands[0].getAsVector(); - const uint64_t* t2 = operands[1].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 2 * sizeof(uint64_t)); memoryData[1] = RegisterValue((char*)t2, 2 * sizeof(uint64_t)); break; @@ -4692,22 +4742,22 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov2d_POST: { // st1 {vt.2d, vt2.2d}, // [xn|sp], <#imm|xm> // STORE - const uint64_t* t = operands[0].getAsVector(); - const uint64_t* t2 = operands[1].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 2 * sizeof(uint64_t)); memoryData[1] = RegisterValue((char*)t2, 2 * sizeof(uint64_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? operands[3].get() + ? srcRegVals[3].get() : 32; - results[0] = operands[2].get() + postIndex; + results[0] = srcRegVals[2].get() + postIndex; break; } case Opcode::AArch64_ST1Twov4s: { // st1 {vt.4s, vt2.4s}, [xn|sp] // STORE - const uint32_t* t = operands[0].getAsVector(); - const uint32_t* t2 = operands[1].getAsVector(); + const uint32_t* t = srcRegVals[0].getAsVector(); + const uint32_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 4 * sizeof(uint32_t)); memoryData[1] = RegisterValue((char*)t2, 4 * sizeof(uint32_t)); break; @@ -4715,30 +4765,30 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov4s_POST: { // st1 {vt.4s, vt2.4s}, // [xn|sp], <#imm|xm> // STORE - const uint32_t* t = operands[0].getAsVector(); - const uint32_t* t2 = operands[1].getAsVector(); + const uint32_t* t = srcRegVals[0].getAsVector(); + const uint32_t* t2 = srcRegVals[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 4 * sizeof(uint32_t)); memoryData[1] = RegisterValue((char*)t2, 4 * sizeof(uint32_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? operands[3].get() + ? srcRegVals[3].get() : 32; - results[0] = operands[2].get() + postIndex; + results[0] = srcRegVals[2].get() + postIndex; break; } case Opcode::AArch64_ST1W: { // st1w {zt.s}, pg, [xn, xm, lsl #2] // STORE - const uint32_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint32_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1W_D: { // st1w {zt.d}, pg, [xn, xm, lsl #2] // STORE - const uint64_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint64_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); @@ -4746,90 +4796,90 @@ void Instruction::execute() { } case Opcode::AArch64_ST1W_IMM: { // st1w {zt.s}, pg, [xn{, #imm, mul vl}] // STORE - const uint32_t* d = operands[0].getAsVector(); - const uint64_t* p = operands[1].getAsVector(); + const uint32_t* d = srcRegVals[0].getAsVector(); + const uint64_t* p = srcRegVals[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1i16: { // st1 {vt.h}[index], [xn] // STORE - const uint16_t* t = operands[0].getAsVector(); + const uint16_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i16_POST: { // st1 {vt.h}[index], [xn], xm // st1 {vt.h}[index], [xn], #2 // STORE - const uint16_t* t = operands[0].getAsVector(); + const uint16_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 2; if (metadata.operandCount == 3) { - offset = operands[2].get(); + offset = srcRegVals[2].get(); } - results[0] = operands[1].get() + offset; + results[0] = srcRegVals[1].get() + offset; break; } case Opcode::AArch64_ST1i32: { // st1 {vt.s}[index], [xn] // STORE - const uint32_t* t = operands[0].getAsVector(); + const uint32_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i32_POST: { // st1 {vt.s}[index], [xn], xm // st1 {vt.s}[index], [xn], #4 // STORE - const uint32_t* t = operands[0].getAsVector(); + const uint32_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 4; if (metadata.operandCount == 3) { - offset = operands[2].get(); + offset = srcRegVals[2].get(); } - results[0] = operands[1].get() + offset; + results[0] = srcRegVals[1].get() + offset; break; } case Opcode::AArch64_ST1i64: { // st1 {vt.d}[index], [xn] // STORE - const uint64_t* t = operands[0].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i64_POST: { // st1 {vt.d}[index], [xn], xm // st1 {vt.d}[index], [xn], #8 // STORE - const uint64_t* t = operands[0].getAsVector(); + const uint64_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 8; if (metadata.operandCount == 3) { - offset = operands[2].get(); + offset = srcRegVals[2].get(); } - results[0] = operands[1].get() + offset; + results[0] = srcRegVals[1].get() + offset; break; } case Opcode::AArch64_ST1i8: { // st1 {vt.b}[index], [xn] // STORE - const uint8_t* t = operands[0].getAsVector(); + const uint8_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i8_POST: { // st1 {vt.b}[index], [xn], xm // st1 {vt.b}[index], [xn], #1 // STORE - const uint8_t* t = operands[0].getAsVector(); + const uint8_t* t = srcRegVals[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 1; if (metadata.operandCount == 3) { - offset = operands[2].get(); + offset = srcRegVals[2].get(); } - results[0] = RegisterValue(operands[1].get() + offset, 8); + results[0] = RegisterValue(srcRegVals[1].get() + offset, 8); break; } case Opcode::AArch64_ST2D_IMM: { // st2d {zt1.d, zt2.d}, pg, [{, // #imm, mul vl}] // STORE - const uint64_t* d1 = operands[0].getAsVector(); - const uint64_t* d2 = operands[1].getAsVector(); - const uint64_t* p = operands[2].getAsVector(); + const uint64_t* d1 = srcRegVals[0].getAsVector(); + const uint64_t* d2 = srcRegVals[1].getAsVector(); + const uint64_t* p = srcRegVals[2].getAsVector(); std::vector memData; bool inActiveBlock = false; @@ -4863,8 +4913,8 @@ void Instruction::execute() { case Opcode::AArch64_ST2Twov4s_POST: { // st2 {vt1.4s, vt2.4s}, [xn], // #imm // STORE - const float* t1 = operands[0].getAsVector(); - const float* t2 = operands[1].getAsVector(); + const float* t1 = srcRegVals[0].getAsVector(); + const float* t2 = srcRegVals[1].getAsVector(); std::vector m1 = {t1[0], t2[0], t1[1], t2[1]}; std::vector m2 = {t1[2], t2[2], t1[3], t2[3]}; memoryData[0] = RegisterValue((char*)m1.data(), 4 * sizeof(float)); @@ -4872,26 +4922,26 @@ void Instruction::execute() { uint64_t offset = 32; if (metadata.operandCount == 4) { - offset = operands[3].get(); + offset = srcRegVals[3].get(); } - results[0] = operands[2].get() + offset; + results[0] = srcRegVals[2].get() + offset; break; } case Opcode::AArch64_STLRB: { // stlrb wt, [xn] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STLRW: // stlr wt, [xn] case Opcode::AArch64_STLRX: { // stlr xt, [xn] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STLXRW: // stlxr ws, wt, [xn] case Opcode::AArch64_STLXRX: { // stlxr ws, xt, [xn] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; @@ -4901,8 +4951,8 @@ void Instruction::execute() { case Opcode::AArch64_STPSi: // stp st1, st2, [xn, #imm] case Opcode::AArch64_STPWi: // stp wt1, wt2, [xn, #imm] case Opcode::AArch64_STPXi: { // stp xt1, xt2, [xn, #imm] - memoryData[0] = operands[0]; - memoryData[1] = operands[1]; + memoryData[0] = srcRegVals[0]; + memoryData[1] = srcRegVals[1]; break; } case Opcode::AArch64_STPDpost: // stp dt1, dt2, [xn], #imm @@ -4910,9 +4960,9 @@ void Instruction::execute() { case Opcode::AArch64_STPSpost: // stp st1, st2, [xn], #imm case Opcode::AArch64_STPWpost: // stp wt1, wt2, [xn], #imm case Opcode::AArch64_STPXpost: { // stp xt1, xt2, [xn], #imm - memoryData[0] = operands[0]; - memoryData[1] = operands[1]; - results[0] = operands[2].get() + metadata.operands[3].imm; + memoryData[0] = srcRegVals[0]; + memoryData[1] = srcRegVals[1]; + results[0] = srcRegVals[2].get() + metadata.operands[3].imm; break; } case Opcode::AArch64_STPDpre: // stp dt1, dt2, [xn, #imm]! @@ -4920,40 +4970,40 @@ void Instruction::execute() { case Opcode::AArch64_STPSpre: // stp st1, st2, [xn, #imm]! case Opcode::AArch64_STPWpre: // stp wt1, wt2, [xn, #imm]! case Opcode::AArch64_STPXpre: { // stp xt1, xt2, [xn, #imm]! - memoryData[0] = operands[0]; - memoryData[1] = operands[1]; + memoryData[0] = srcRegVals[0]; + memoryData[1] = srcRegVals[1]; results[0] = - operands[2].get() + metadata.operands[2].mem.disp; + srcRegVals[2].get() + metadata.operands[2].mem.disp; break; } case Opcode::AArch64_STRBBpost: { // strb wd, [xn], #imm // STORE - memoryData[0] = operands[0]; - results[0] = operands[1].get() + metadata.operands[2].imm; + memoryData[0] = srcRegVals[0]; + results[0] = srcRegVals[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRBBpre: { // strb wd, [xn, #imm]! // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; results[0] = - operands[1].get() + metadata.operands[1].mem.disp; + srcRegVals[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRBBroW: { // strb wd, // [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRBBroX: { // strb wd, // [xn, xm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRBBui: { // strb wd, [xn, #imm] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRBui: // str bt, [xn, #imm] @@ -4963,7 +5013,7 @@ void Instruction::execute() { case Opcode::AArch64_STRSui: // str st, [xn, #imm] case Opcode::AArch64_STRWui: // str wt, [xn, #imm] case Opcode::AArch64_STRXui: { // str xt, [xn, #imm] - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRBpost: // str bt, [xn], #imm @@ -4973,8 +5023,8 @@ void Instruction::execute() { case Opcode::AArch64_STRSpost: // str st, [xn], #imm case Opcode::AArch64_STRWpost: // str wt, [xn], #imm case Opcode::AArch64_STRXpost: { // str xt, [xn], #imm - memoryData[0] = operands[0]; - results[0] = operands[1].get() + metadata.operands[2].imm; + memoryData[0] = srcRegVals[0]; + results[0] = srcRegVals[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRBpre: // str bt, [xn, #imm]! @@ -4984,110 +5034,110 @@ void Instruction::execute() { case Opcode::AArch64_STRSpre: // str st, [xn, #imm]! case Opcode::AArch64_STRWpre: // str wt, [xn, #imm]! case Opcode::AArch64_STRXpre: { // str xt, [xn, #imm]! - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; results[0] = - operands[1].get() + metadata.operands[1].mem.disp; + srcRegVals[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRDroW: { // str dt, [xn, wm{, #extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRDroX: { // str dt, [xn, xm{, #extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRHHpost: { // strh wt, [xn], #imm // STORE - memoryData[0] = operands[0]; - results[0] = operands[1].get() + metadata.operands[2].imm; + memoryData[0] = srcRegVals[0]; + results[0] = srcRegVals[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRHHpre: { // strh wd, [xn, #imm]! // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; results[0] = - operands[1].get() + metadata.operands[1].mem.disp; + srcRegVals[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRHHroW: { // strh wd, // [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRHHroX: { // strh wd, // [xn, xm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRHHui: { // strh wt, [xn, #imm] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRQroX: { // str qt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRSroW: { // str st, [xn, wm{, #extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRSroX: { // str st, [xn, xm{, #extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRWroW: { // str wd, [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRWroX: { // str wt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRXroW: { // str xd, [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STRXroX: { // str xt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STR_PXI: { // str pt, [xn{, #imm, mul vl}] // STORE const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint8_t* p = operands[0].getAsVector(); + const uint8_t* p = srcRegVals[0].getAsVector(); memoryData[0] = RegisterValue((char*)p, partition_num); break; } case Opcode::AArch64_STR_ZXI: { // str zt, [xn{, #imm, mul vl}] // STORE const uint16_t partition_num = VL_bits / 8; - const uint8_t* z = operands[0].getAsVector(); + const uint8_t* z = srcRegVals[0].getAsVector(); memoryData[0] = RegisterValue((char*)z, partition_num); break; } case Opcode::AArch64_STURBBi: { // sturb wd, [xn, #imm] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STURDi: // stur dt, [xn, #imm] case Opcode::AArch64_STURHHi: { // sturh wt, [xn, #imm] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STURQi: // stur qt, [xn, #imm] @@ -5095,151 +5145,157 @@ void Instruction::execute() { case Opcode::AArch64_STURWi: // stur wt, [xn, #imm] case Opcode::AArch64_STURXi: { // stur xt, [xn, #imm] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::AArch64_STXRW: { // stxr ws, wt, [xn] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; } case Opcode::AArch64_STXRX: { // stxr ws, xt, [xn] // STORE - memoryData[0] = operands[0]; + memoryData[0] = srcRegVals[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; } case Opcode::AArch64_SUBSWri: { // subs wd, wn, #imm auto [result, nzcv] = - arithmeticHelp::subShift_imm(operands, metadata, true); + arithmeticHelp::subShift_imm(srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSWrs: { // subs wd, wn, wm{, shift #amount} auto [result, nzcv] = - arithmeticHelp::subShift_3ops(operands, metadata, true); + arithmeticHelp::subShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSWrx: { // subs wd, wn, wm{, extend #amount} - auto [result, nzcv] = - arithmeticHelp::subExtend_3ops(operands, metadata, true); + auto [result, nzcv] = arithmeticHelp::subExtend_3ops( + srcRegVals, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSXri: { // subs xd, xn, #imm auto [result, nzcv] = - arithmeticHelp::subShift_imm(operands, metadata, true); + arithmeticHelp::subShift_imm(srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBSXrs: { // subs xd, xn, xm{, shift #amount} auto [result, nzcv] = - arithmeticHelp::subShift_3ops(operands, metadata, true); + arithmeticHelp::subShift_3ops(srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBSXrx: // subs xd, xn, wm{, extend #amount} case Opcode::AArch64_SUBSXrx64: { // subs xd, xn, xm{, extend #amount} - auto [result, nzcv] = - arithmeticHelp::subExtend_3ops(operands, metadata, true); + auto [result, nzcv] = arithmeticHelp::subExtend_3ops( + srcRegVals, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBWri: { // sub wd, wn, #imm{, } auto [result, nzcv] = - arithmeticHelp::subShift_imm(operands, metadata, false); + arithmeticHelp::subShift_imm(srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_SUBWrs: { // sub wd, wn, wm{, shift #amount} - auto [result, nzcv] = - arithmeticHelp::subShift_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::subShift_3ops( + srcRegVals, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_SUBXri: { // sub xd, xn, #imm{, } auto [result, nzcv] = - arithmeticHelp::subShift_imm(operands, metadata, false); + arithmeticHelp::subShift_imm(srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUBXrs: { // sub xd, xn, xm{, shift #amount} - auto [result, nzcv] = - arithmeticHelp::subShift_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::subShift_3ops( + srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUBXrx: // sub xd, xn, wm{, extend #amount} case Opcode::AArch64_SUBXrx64: { // sub xd, xn, xm{, extend #amount} - auto [result, nzcv] = - arithmeticHelp::subExtend_3ops(operands, metadata, false); + auto [result, nzcv] = arithmeticHelp::subExtend_3ops( + srcRegVals, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUB_ZZZ_B: { // sub zd.b, zn.b, zm.b - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_D: { // sub zd.d, zn.d, zm.d - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_H: { // sub zd.h, zn.h, zm.h - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_S: { // sub zd.s, zn.s, zm.s - results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); + results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_SUBv16i8: { // sub vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); break; } case Opcode::AArch64_SUBv1i64: { // sub dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); + srcRegVals, + [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); break; } case Opcode::AArch64_SUBv2i32: { // sub vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); + srcRegVals, + [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); break; } case Opcode::AArch64_SUBv2i64: { // sub vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); + srcRegVals, + [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); break; } case Opcode::AArch64_SUBv4i16: { // sub vd.4h, vn.4h, vm.4h results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint64_t x, uint16_t y) -> uint16_t { return x - y; }); + srcRegVals, + [](uint64_t x, uint16_t y) -> uint16_t { return x - y; }); break; } case Opcode::AArch64_SUBv4i32: { // sub vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); + srcRegVals, + [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); break; } case Opcode::AArch64_SUBv8i16: { // sub vd.8h, vn.8h, vm.8h results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint16_t x, uint16_t y) -> uint16_t { return x - y; }); + srcRegVals, + [](uint16_t x, uint16_t y) -> uint16_t { return x - y; }); break; } case Opcode::AArch64_SUBv8i8: { // sub vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - operands, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); + srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); break; } case Opcode::AArch64_SVC: { // svc #imm @@ -5249,7 +5305,7 @@ void Instruction::execute() { } case Opcode::AArch64_SXTW_ZPmZ_D: { // sxtw zd.d, pg/m, zn.d results[0] = - sveHelp::sveSxtPredicated(operands, VL_bits); + sveHelp::sveSxtPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_SYSxt: { // sys #, cn, cm, #{, xt} @@ -5267,465 +5323,465 @@ void Instruction::execute() { } case Opcode::AArch64_TBLv16i8Four: { // tbl Vd.16b {Vn.16b, Vn+1.16b, // Vn+2.16b,Vn+3.16b } Vm.16b - results[0] = neonHelp::vecTbl<16>(operands, metadata); + results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv16i8One: { // tbl Vd.16b {Vn.16b} Vm.16b - results[0] = neonHelp::vecTbl<16>(operands, metadata); + results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv16i8Three: { // tbl Vd.16b {Vn.16b, Vn+1.16b, // Vn+2.16b } Vm.16b - results[0] = neonHelp::vecTbl<16>(operands, metadata); + results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv16i8Two: { // tbl Vd.16b {Vn.16b, Vn+1.16b } // Vm.16b - results[0] = neonHelp::vecTbl<16>(operands, metadata); + results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv8i8Four: { // tbl Vd.8b {Vn.16b, Vn+1.16b, // Vn+2.16b,Vn+3.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(operands, metadata); + results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv8i8One: { // tbl Vd.8b {Vn.16b} Vm.8b - results[0] = neonHelp::vecTbl<8>(operands, metadata); + results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv8i8Three: { // tbl Vd.8b {Vn.16b, Vn+1.16b, // Vn+2.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(operands, metadata); + results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); break; } case Opcode::AArch64_TBLv8i8Two: { // tbl Vd.8b {Vn.16b, Vn+1.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(operands, metadata); + results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); break; } case Opcode::AArch64_TBNZW: { // tbnz wn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - operands, metadata, instructionAddress_, true); + srcRegVals, metadata, instructionAddress_, true); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBNZX: { // tbnz xn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - operands, metadata, instructionAddress_, true); + srcRegVals, metadata, instructionAddress_, true); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBZW: { // tbz wn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - operands, metadata, instructionAddress_, false); + srcRegVals, metadata, instructionAddress_, false); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBZX: { // tbz xn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - operands, metadata, instructionAddress_, false); + srcRegVals, metadata, instructionAddress_, false); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TRN1_ZZZ_B: { // trn1 zd.b, zn.b, zm.b - results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_D: { // trn1 zd.d, zn.d, zm.d - results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_H: { // trn1 zd.h, zn.h, zm.h - results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_S: { // trn1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN1v16i8: { // trn1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v2i32: { // trn1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v2i64: { // trn1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v4i16: { // trn1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v4i32: { // trn1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v8i16: { // trn1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN1v8i8: { // trn1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecTrn1(operands); + results[0] = neonHelp::vecTrn1(srcRegVals); break; } case Opcode::AArch64_TRN2_ZZZ_B: { // trn2 zd.b, zn.b, zm.b - results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_D: { // trn2 zd.d, zn.d, zm.d - results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_H: { // trn2 zd.h, zn.h, zm.h - results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_S: { // trn2 zd.s, zn.s, zm.s - results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); break; } case Opcode::AArch64_TRN2v16i8: { // trn2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v2i32: { // trn2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v2i64: { // trn2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v4i16: { // trn2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v4i32: { // trn2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v8i16: { // trn2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_TRN2v8i8: { // trn2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecTrn2(operands); + results[0] = neonHelp::vecTrn2(srcRegVals); break; } case Opcode::AArch64_UADDV_VPZ_B: { // uaddv dd, pg, zn.b - results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); + results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_D: { // uaddv dd, pg, zn.d - results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); + results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_H: { // uaddv dd, pg, zn.h - results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); + results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_S: { // uaddv dd, pg, zn.s - results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); + results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); break; } case Opcode::AArch64_UBFMWri: { // ubfm wd, wn, #immr, #imms - results[0] = { - bitmanipHelp::bfm_2imms(operands, metadata, false, true), - 8}; + results[0] = {bitmanipHelp::bfm_2imms(srcRegVals, metadata, + false, true), + 8}; break; } case Opcode::AArch64_UBFMXri: { // ubfm xd, xn, #immr, #imms - results[0] = - bitmanipHelp::bfm_2imms(operands, metadata, false, true); + results[0] = bitmanipHelp::bfm_2imms(srcRegVals, metadata, + false, true); break; } case Opcode::AArch64_UCVTFUWDri: { // ucvtf dd, wn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUWSri: { // ucvtf sd, wn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUXDri: { // ucvtf dd, xn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUXSri: { // ucvtf sd, xn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UCVTFv1i32: { // ucvtf sd, sn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UCVTFv1i64: { // ucvtf dd, dn - results[0] = {static_cast(operands[0].get()), 256}; + results[0] = {static_cast(srcRegVals[0].get()), 256}; break; } case Opcode::AArch64_UDIVWr: { // udiv wd, wn, wm - results[0] = {divideHelp::div_3ops(operands), 8}; + results[0] = {divideHelp::div_3ops(srcRegVals), 8}; break; } case Opcode::AArch64_UDIVXr: { // udiv xd, xn, xm - results[0] = {divideHelp::div_3ops(operands), 8}; + results[0] = {divideHelp::div_3ops(srcRegVals), 8}; break; } case Opcode::AArch64_UMADDLrrr: { // umaddl xd, wn, wm, xa - results[0] = multiplyHelp::maddl_4ops(operands); + results[0] = multiplyHelp::maddl_4ops(srcRegVals); break; } case Opcode::AArch64_UMAXPv16i8: { // umaxp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUMaxP(operands); + results[0] = neonHelp::vecUMaxP(srcRegVals); break; } case Opcode::AArch64_UMINPv16i8: { // uminp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUMinP(operands); + results[0] = neonHelp::vecUMinP(srcRegVals); break; } case Opcode::AArch64_UMOVvi32_idx0: // umov wd, vn.s[0] case Opcode::AArch64_UMOVvi32: { // umov wd, vn.s[index] - const uint32_t* vec = operands[0].getAsVector(); + const uint32_t* vec = srcRegVals[0].getAsVector(); results[0] = {vec[metadata.operands[1].vector_index], 8}; break; } case Opcode::AArch64_UMOVvi64_idx0: // umov xd, vn.d[0] case Opcode::AArch64_UMOVvi64: { // umov xd, vn.d[index] - const uint64_t* vec = operands[0].getAsVector(); + const uint64_t* vec = srcRegVals[0].getAsVector(); results[0] = vec[metadata.operands[1].vector_index]; break; } case Opcode::AArch64_UMOVvi8_idx0: // umov wd, vn.b[0] case Opcode::AArch64_UMOVvi8: { // umov wd, vn.b[index] - const uint8_t* vec = operands[0].getAsVector(); + const uint8_t* vec = srcRegVals[0].getAsVector(); results[0] = {vec[metadata.operands[1].vector_index], 8}; break; } case Opcode::AArch64_UMSUBLrrr: { // umsubl xd, wn, wm, xa - results[0] = arithmeticHelp::msubl_4ops(operands); + results[0] = arithmeticHelp::msubl_4ops(srcRegVals); break; } case Opcode::AArch64_UMULHrr: { // umulh xd, xn, xm - results[0] = AuxFunc::mulhi(operands[0].get(), - operands[1].get()); + results[0] = AuxFunc::mulhi(srcRegVals[0].get(), + srcRegVals[1].get()); break; } case Opcode::AArch64_UQDECD_WPiI: { // uqdecd wd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(operands, metadata, VL_bits); + sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_UQDECD_XPiI: { // uqdecd xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(operands, metadata, VL_bits); + sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_UQDECH_XPiI: { // uqdech xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(operands, metadata, VL_bits); + sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_UQDECW_XPiI: { // uqdecw xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(operands, metadata, VL_bits); + sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); break; } case Opcode::AArch64_USHLLv16i8_shift: { // ushll2 vd.8h, vn.16b, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, true); + srcRegVals, metadata, true); break; } case Opcode::AArch64_USHLLv4i16_shift: { // ushll vd.4s, vn.4h, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, false); + srcRegVals, metadata, false); break; } case Opcode::AArch64_USHLLv8i16_shift: { // ushll2 vd.4s, vn.8h, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, true); + srcRegVals, metadata, true); break; } case Opcode::AArch64_USHLLv8i8_shift: { // ushll vd.8h, vn.8b, #imm results[0] = neonHelp::vecShllShift_vecImm( - operands, metadata, false); + srcRegVals, metadata, false); break; } case Opcode::AArch64_UUNPKHI_ZZ_D: { // uunpkhi zd.d, zn.s - results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, true); + results[0] = sveHelp::sveUnpk_vecs(srcRegVals, + VL_bits, true); break; } case Opcode::AArch64_UUNPKHI_ZZ_H: { // uunpkhi zd.h, zn.b results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, true); + sveHelp::sveUnpk_vecs(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_UUNPKHI_ZZ_S: { // uunpkhi zd.s, zn.h - results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, true); + results[0] = sveHelp::sveUnpk_vecs(srcRegVals, + VL_bits, true); break; } case Opcode::AArch64_UUNPKLO_ZZ_D: { // uunpklo zd.d, zn.s - results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, false); + results[0] = sveHelp::sveUnpk_vecs(srcRegVals, + VL_bits, false); break; } case Opcode::AArch64_UUNPKLO_ZZ_H: { // uunpklo zd.h, zn.b - results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, false); + results[0] = sveHelp::sveUnpk_vecs(srcRegVals, + VL_bits, false); break; } case Opcode::AArch64_UUNPKLO_ZZ_S: { // uunpklo zd.s, zn.h - results[0] = - sveHelp::sveUnpk_vecs(operands, VL_bits, false); + results[0] = sveHelp::sveUnpk_vecs(srcRegVals, + VL_bits, false); break; } case Opcode::AArch64_UZP1_ZZZ_S: { // uzp1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveUzp_vecs(operands, VL_bits, true); + results[0] = sveHelp::sveUzp_vecs(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_UZP1v16i8: { // uzp1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v2i32: { // uzp1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v2i64: { // uzp1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v4i16: { // uzp1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v4i32: { // uzp1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v8i16: { // uzp1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP1v8i8: { // uzp1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecUzp(operands, true); + results[0] = neonHelp::vecUzp(srcRegVals, true); break; } case Opcode::AArch64_UZP2v16i8: { // uzp2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v2i32: { // uzp2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v2i64: { // uzp2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v4i16: { // uzp2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v4i32: { // uzp2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v8i16: { // uzp2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_UZP2v8i8: { // uzp2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecUzp(operands, false); + results[0] = neonHelp::vecUzp(srcRegVals, false); break; } case Opcode::AArch64_WHILELO_PWW_B: { // whilelo pd.b, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_D: { // whilelo pd.d, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_H: { // whilelo pd.h, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_S: { // whilelo pd.s, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_B: { // whilelo pd.b, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_D: { // whilelo pd.d, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_H: { // whilelo pd.h, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_S: { // whilelo pd.s, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_B: { // whilelt pd.b, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_D: { // whilelt pd.d, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_H: { // whilelt pd.h, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_S: { // whilelt pd.s, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(operands, VL_bits, true); + sveHelp::sveWhilelo(srcRegVals, VL_bits, true); results[0] = nzcv; results[1] = output; break; @@ -5735,119 +5791,122 @@ void Instruction::execute() { break; } case Opcode::AArch64_XTNv2i32: { // xtn vd.2s, vn.2d - results[0] = neonHelp::vecXtn(operands, false); + results[0] = neonHelp::vecXtn(srcRegVals, false); break; } case Opcode::AArch64_XTNv4i16: { // xtn vd.4h, vn.4s - results[0] = neonHelp::vecXtn(operands, false); + results[0] = neonHelp::vecXtn(srcRegVals, false); break; } case Opcode::AArch64_XTNv4i32: { // xtn2 vd.4s, vn.2d - results[0] = neonHelp::vecXtn(operands, true); + results[0] = neonHelp::vecXtn(srcRegVals, true); break; } case Opcode::AArch64_ZIP1_PPP_B: { // zip1 pd.b, pn.b, pm.b - results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); + results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_D: { // zip1 pd.d, pn.d, pm.d - results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); + results[0] = + sveHelp::sveZip_preds(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_H: { // zip1 pd.h, pn.h, pm.h - results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); + results[0] = + sveHelp::sveZip_preds(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_S: { // zip1 pd.s, pn.s, pm.s - results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); + results[0] = + sveHelp::sveZip_preds(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1_ZZZ_D: { // zip1 zd.d, zn.d, zm.d - results[0] = sveHelp::sveZip_vecs(operands, VL_bits, false); + results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1_ZZZ_S: { // zip1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveZip_vecs(operands, VL_bits, false); + results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, false); break; } case Opcode::AArch64_ZIP1v16i8: { // zip1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v2i32: { // zip1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v2i64: { // zip1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v4i16: { // zip1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v4i32: { // zip1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v8i16: { // zip1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP1v8i8: { // zip1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecZip(operands, false); + results[0] = neonHelp::vecZip(srcRegVals, false); break; } case Opcode::AArch64_ZIP2_PPP_B: { // zip2 pd.b, pn.b, pm.b - results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); + results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_D: { // zip2 pd.d, pn.d, pm.d - results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); + results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_H: { // zip2 pd.h, pn.h, pm.h - results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); + results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_S: { // zip2 pd.s, pn.s, pm.s - results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); + results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2_ZZZ_D: { // zip2 zd.d, zn.d, zm.d - results[0] = sveHelp::sveZip_vecs(operands, VL_bits, true); + results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2_ZZZ_S: { // zip2 zd.s, zn.s, zm.s - results[0] = sveHelp::sveZip_vecs(operands, VL_bits, true); + results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, true); break; } case Opcode::AArch64_ZIP2v16i8: { // zip2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v2i32: { // zip2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v2i64: { // zip2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v4i16: { // zip2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v4i32: { // zip2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v8i16: { // zip2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZIP2v8i8: { // zip2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecZip(operands, true); + results[0] = neonHelp::vecZip(srcRegVals, true); break; } case Opcode::AArch64_ZERO_M: { // zero {mask} diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 754f11f565..7e8afdd08f 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -36,8 +36,7 @@ const span Instruction::getSourceRegisters() const { } const span Instruction::getSourceOperands() const { - return {const_cast(sourceRegValues.data()), - sourceRegValues.size()}; + return {const_cast(srcRegVals.data()), srcRegVals.size()}; } const span Instruction::getDestinationRegisters() const { @@ -46,7 +45,7 @@ const span Instruction::getDestinationRegisters() const { } bool Instruction::isOperandReady(int index) const { - return static_cast(sourceRegValues[index]); + return static_cast(srcRegVals[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { @@ -62,7 +61,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { assert(value.size() > 0 && "Attempted to provide an uninitialised RegisterValue"); - sourceRegValues[i] = value; + srcRegVals[i] = value; numSourceOperandsPending--; } diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index a79d592313..77d51119fa 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -19,31 +19,31 @@ span Instruction::generateAddresses() { assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = sourceRegValues[1].get(); + address = srcRegVals[1].get(); } else if (isLoad() && isAtomic()) { // Load reserved // Metadata operand[1] corresponds to instruction sourceRegValues[0] assert(metadata.operands[1].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = sourceRegValues[0].get(); + address = srcRegVals[0].get(); } else if (isStoreAddress() && isAtomic()) { // Store conditional assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = sourceRegValues[1].get(); + address = srcRegVals[1].get(); } else if (isLoad()) { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - address = sourceRegValues[0].get() + imm; + address = srcRegVals[0].get() + imm; } else { assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); - address = sourceRegValues[1].get() + imm; + address = srcRegVals[1].get() + imm; } // Atomics @@ -109,7 +109,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_W_RL: [[fallthrough]]; case Opcode::RISCV_LR_W_AQ_RL: { - setMemoryAddresses({{sourceRegValues[0].get(), 4}}); + setMemoryAddresses({{srcRegVals[0].get(), 4}}); break; } case Opcode::RISCV_LR_D: @@ -119,7 +119,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_D_RL: [[fallthrough]]; case Opcode::RISCV_LR_D_AQ_RL: { - setMemoryAddresses({{sourceRegValues[0].get(), 8}}); + setMemoryAddresses({{srcRegVals[0].get(), 8}}); break; } case Opcode::RISCV_SC_W: @@ -129,7 +129,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_W_RL: [[fallthrough]]; case Opcode::RISCV_SC_W_AQ_RL: { - setMemoryAddresses({{sourceRegValues[1].get(), 4}}); + setMemoryAddresses({{srcRegVals[1].get(), 4}}); break; } case Opcode::RISCV_SC_D: @@ -139,7 +139,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_D_RL: [[fallthrough]]; case Opcode::RISCV_SC_D_AQ_RL: { - setMemoryAddresses({{sourceRegValues[1].get(), 8}}); + setMemoryAddresses({{srcRegVals[1].get(), 8}}); break; } default: diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index b9e7867fbf..867049ca59 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -150,7 +150,7 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - sourceRegValues[sourceRegisterCount] = RegisterValue(0, 8); + srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); } else { numSourceOperandsPending++; } @@ -192,7 +192,7 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - sourceRegValues[sourceRegisterCount] = RegisterValue(0, 8); + srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); } else { numSourceOperandsPending++; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 47d29d0a8d..75286f0f63 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -221,137 +221,137 @@ void Instruction::execute() { case Opcode::RISCV_SW: // SW rs1,rs2,imm [[fallthrough]]; case Opcode::RISCV_SD: { // SD rs1,rs2,imm - memoryData[0] = sourceRegValues[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::RISCV_SLL: { // SLL rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); const int64_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLW: { // SLLW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); const int32_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits int64_t out = signExtendW(static_cast(rs1 << rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); const int32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRL: { // SRL rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLW: { // SRLW rd,rs1,rs2 - const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs1 = srcRegVals[0].get(); const uint32_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt - const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs1 = srcRegVals[0].get(); const uint32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRA: { // SRA rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); const int64_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAW: { // SRAW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); const int32_t rs2 = - sourceRegValues[1].get() & 63; // Only use lowest 6 bits + srcRegVals[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); const int32_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADD: { // ADD rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDW: { // ADDW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); - const int32_t rs2 = sourceRegValues[1].get(); + const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs2 = srcRegVals[1].get(); int64_t out = static_cast(static_cast(rs1 + rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t rs2 = imm; uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); const int32_t sourceImm = imm; uint64_t out = signExtendW(rs1 + sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUB: { // SUB rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); uint64_t out = static_cast(rs1 - rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUBW: { // SUBW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); - const int32_t rs2 = sourceRegValues[1].get(); + const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs2 = srcRegVals[1].get(); int64_t out = static_cast(static_cast(rs1 - rs2)); results[0] = RegisterValue(out, 8); break; @@ -369,50 +369,50 @@ void Instruction::execute() { break; } case Opcode::RISCV_XOR: { // XOR rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); uint64_t out = static_cast(rs1 ^ rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 ^ sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_OR: { // OR rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); uint64_t out = static_cast(rs1 | rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 | sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AND: { // AND rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); uint64_t out = static_cast(rs1 & rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 & sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLT: { // SLT rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -421,8 +421,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTU: { // SLTU rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -431,7 +431,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); const int64_t sourceImm = imm; if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); @@ -441,7 +441,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); const uint64_t sourceImm = static_cast(imm); if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); @@ -451,8 +451,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BEQ: { // BEQ rs1,rs2,imm - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs1 == rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -463,8 +463,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BNE: { // BNE rs1,rs2,imm - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs1 != rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -476,8 +476,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLT: { // BLT rs1,rs2,imm - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -488,8 +488,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLTU: { // BLTU rs1,rs2,imm - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -500,8 +500,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGE: { // BGE rs1,rs2,imm - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -512,8 +512,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGEU: { // BGEU rs1,rs2,imm - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -530,8 +530,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm - branchAddress_ = (sourceRegValues[0].get() + imm) & - ~1; // Set LSB of result to 0 + branchAddress_ = + (srcRegVals[0].get() + imm) & ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; @@ -593,7 +593,7 @@ void Instruction::execute() { // if not raise address-misaligned/access-fault exception // TODO use aq and rl bits to prevent reordering with other memory // operations - memoryData[0] = sourceRegValues[0]; + memoryData[0] = srcRegVals[0]; results[0] = RegisterValue(static_cast(0), 8); break; } @@ -607,7 +607,7 @@ void Instruction::execute() { // TODO raise address misaligned or access-fault errors // TODO account for AQ and RL bits int64_t rd = signExtendW(memoryData[0].get()); - int32_t rs2 = sourceRegValues[0].get(); + int32_t rs2 = srcRegVals[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -617,7 +617,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOSWAP_D_RL: case Opcode::RISCV_AMOSWAP_D_AQ_RL: { uint64_t rd = memoryData[0].get(); - uint64_t rs2 = sourceRegValues[0].get(); + uint64_t rs2 = srcRegVals[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -628,8 +628,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd + sourceRegValues[0].get()); + memoryData[0] = static_cast(rd + srcRegVals[0].get()); break; } case Opcode::RISCV_AMOADD_D: // AMOADD.D rd,rs1,rs2 @@ -638,8 +637,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd + sourceRegValues[0].get()); + memoryData[0] = static_cast(rd + srcRegVals[0].get()); break; } case Opcode::RISCV_AMOAND_W: // AMOAND.W rd,rs1,rs2 @@ -648,8 +646,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd & sourceRegValues[0].get()); + memoryData[0] = static_cast(rd & srcRegVals[0].get()); break; } case Opcode::RISCV_AMOAND_D: // AMOAND.D rd,rs1,rs2 @@ -658,8 +655,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd & sourceRegValues[0].get()); + memoryData[0] = static_cast(rd & srcRegVals[0].get()); break; } case Opcode::RISCV_AMOOR_W: // AMOOR.W rd,rs1,rs2 @@ -668,8 +664,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd | sourceRegValues[0].get()); + memoryData[0] = static_cast(rd | srcRegVals[0].get()); break; } case Opcode::RISCV_AMOOR_D: // AMOOR.D rd,rs1,rs2 @@ -678,8 +673,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd | sourceRegValues[0].get()); + memoryData[0] = static_cast(rd | srcRegVals[0].get()); break; } case Opcode::RISCV_AMOXOR_W: // AMOXOR.W rd,rs1,rs2 @@ -688,8 +682,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd ^ sourceRegValues[0].get()); + memoryData[0] = static_cast(rd ^ srcRegVals[0].get()); break; } case Opcode::RISCV_AMOXOR_D: // AMOXOR.D rd,rs1,rs2 @@ -698,8 +691,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = - static_cast(rd ^ sourceRegValues[0].get()); + memoryData[0] = static_cast(rd ^ srcRegVals[0].get()); break; } @@ -708,8 +700,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMIN_W_RL: case Opcode::RISCV_AMOMIN_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = std::min(memoryData[0].get(), - sourceRegValues[0].get()); + memoryData[0] = + std::min(memoryData[0].get(), srcRegVals[0].get()); break; } case Opcode::RISCV_AMOMIN_D: // AMOMIN.D rd,rs1,rs2 @@ -719,7 +711,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::min(rd, sourceRegValues[0].get())); + static_cast(std::min(rd, srcRegVals[0].get())); break; } case Opcode::RISCV_AMOMINU_W: // AMOMINU.W rd,rs1,rs2 @@ -728,7 +720,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOMINU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); memoryData[0] = std::min(memoryData[0].get(), - sourceRegValues[0].get()); + srcRegVals[0].get()); break; } case Opcode::RISCV_AMOMINU_D: // AMOMINU.D rd,rs1,rs2 @@ -737,8 +729,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMINU_D_AQ_RL: { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast( - std::min(rd, sourceRegValues[0].get())); + memoryData[0] = + static_cast(std::min(rd, srcRegVals[0].get())); break; } @@ -747,8 +739,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAX_W_RL: case Opcode::RISCV_AMOMAX_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = std::max(memoryData[0].get(), - sourceRegValues[0].get()); + memoryData[0] = + std::max(memoryData[0].get(), srcRegVals[0].get()); break; } case Opcode::RISCV_AMOMAX_D: // AMOMAX.D rd,rs1,rs2 @@ -758,7 +750,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::max(rd, sourceRegValues[0].get())); + static_cast(std::max(rd, srcRegVals[0].get())); break; } case Opcode::RISCV_AMOMAXU_W: // AMOMAXU.W rd,rs1,rs2 @@ -767,7 +759,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAXU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); memoryData[0] = std::max(memoryData[0].get(), - sourceRegValues[0].get()); + srcRegVals[0].get()); break; } case Opcode::RISCV_AMOMAXU_D: // AMOMAXU.D rd,rs1,rs2 @@ -776,15 +768,15 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAXU_D_AQ_RL: { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast( - std::max(rd, sourceRegValues[0].get())); + memoryData[0] = + static_cast(std::max(rd, srcRegVals[0].get())); break; } // Integer multiplication division extension (M) case Opcode::RISCV_MUL: { // MUL rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); results[0] = RegisterValue(static_cast(rs1 * rs2), 8); break; } @@ -797,8 +789,8 @@ void Instruction::execute() { // break; // } case Opcode::RISCV_MULHU: { // MULHU rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); results[0] = RegisterValue(mulhiuu(rs1, rs2), 8); break; } @@ -811,15 +803,15 @@ void Instruction::execute() { // break; // } case Opcode::RISCV_MULW: { // MULW rd,rs1,rs2 - const uint32_t rs1 = sourceRegValues[0].get(); - const uint32_t rs2 = sourceRegValues[1].get(); + const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs2 = srcRegVals[1].get(); results[0] = RegisterValue(signExtendW(rs1 * rs2), 8); break; } case Opcode::RISCV_DIV: { // DIV rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -832,8 +824,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVW: { // DIVW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); - const int32_t rs2 = sourceRegValues[1].get(); + const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -847,8 +839,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVU: { // DIVU rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -858,8 +850,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVUW: { // DIVUW rd,rs1,rs2 - const uint32_t rs1 = sourceRegValues[0].get(); - const uint32_t rs2 = sourceRegValues[1].get(); + const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -870,8 +862,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REM: { // REM rd,rs1,rs2 - const int64_t rs1 = sourceRegValues[0].get(); - const int64_t rs2 = sourceRegValues[1].get(); + const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(rs1), 8); @@ -884,8 +876,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMW: { // REMW rd,rs1,rs2 - const int32_t rs1 = sourceRegValues[0].get(); - const int32_t rs2 = sourceRegValues[1].get(); + const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -899,8 +891,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMU: { // REMU rd,rs1,rs2 - const uint64_t rs1 = sourceRegValues[0].get(); - const uint64_t rs2 = sourceRegValues[1].get(); + const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(rs1, 8); @@ -910,8 +902,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMUW: { // REMUW rd,rs1,rs2 - const uint32_t rs1 = sourceRegValues[0].get(); - const uint32_t rs2 = sourceRegValues[1].get(); + const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs2 = srcRegVals[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -967,11 +959,11 @@ void Instruction::execute() { // Single-Precision Floating-Point (F) // Double-Precision Floating-Point (D) case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm - memoryData[0] = sourceRegValues[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::RISCV_FSW: { // FSW rs1,rs2,imm - memoryData[0] = sourceRegValues[0]; + memoryData[0] = srcRegVals[0]; break; } case Opcode::RISCV_FLD: { // FLD rd,rs1,imm @@ -987,8 +979,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_D: { // FADD.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(rs1 + rs2, 8); }); @@ -997,8 +989,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_S: { // FADD.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(rs1 + rs2), 8); }); @@ -1007,8 +999,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_D: { // FSUB.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(rs1 - rs2, 8); }); @@ -1018,8 +1010,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_S: { // FSUB.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(rs1 - rs2), 8); }); @@ -1029,8 +1021,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_D: { // FDIV.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(rs1 / rs2, 8); }); @@ -1040,8 +1032,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_S: { // FDIV.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(rs1 / rs2), 8); }); @@ -1051,8 +1043,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_D: { // FMUL.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(rs1 * rs2, 8); }); @@ -1062,8 +1054,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_S: { // FMUL.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(rs1 * rs2), 8); }); @@ -1073,7 +1065,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_D: { // FSQRT.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); const double sqrtAns = sqrt(rs1); @@ -1089,7 +1081,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_S: { // FSQRT.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); const float sqrtAns = sqrtf(rs1); @@ -1104,8 +1096,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMIN_D: { // FMIN.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); // cpp fmin reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1120,8 +1112,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMIN_S: { // FMIN.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); // Comments regarding fminf similar to RISCV_FMIN_D if (rs1 == 0 && rs2 == 0) { @@ -1134,8 +1126,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMAX_D: { // FMAX.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); // cpp fmax reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1149,8 +1141,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMAX_S: { // FMAX.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); // Comments regarding fmaxf similar to RISCV_FMAX_D if (rs1 == 0 && rs2 == 0) { @@ -1170,9 +1162,9 @@ void Instruction::execute() { // the addend is a quiet NaN. setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); - const double rs3 = sourceRegValues[2].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); + const double rs3 = srcRegVals[2].get(); results[0] = RegisterValue(fma(rs1, rs2, rs3), 8); }); @@ -1182,9 +1174,9 @@ void Instruction::execute() { case Opcode::RISCV_FMADD_S: { // FMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); - const float rs3 = checkNanBox(sourceRegValues[2]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); + const float rs3 = checkNanBox(srcRegVals[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1198,9 +1190,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_D: { // FNMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); - const double rs3 = sourceRegValues[2].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); + const double rs3 = srcRegVals[2].get(); results[0] = RegisterValue(-(rs1 * rs2) + rs3, 8); }); @@ -1210,9 +1202,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_S: { // FNMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); - const float rs3 = checkNanBox(sourceRegValues[2]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); + const float rs3 = checkNanBox(srcRegVals[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1226,9 +1218,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_D: { // FMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); - const double rs3 = sourceRegValues[2].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); + const double rs3 = srcRegVals[2].get(); results[0] = RegisterValue((rs1 * rs2) - rs3, 8); }); @@ -1238,9 +1230,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_S: { // FMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); - const float rs3 = checkNanBox(sourceRegValues[2]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); + const float rs3 = checkNanBox(srcRegVals[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1254,9 +1246,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_D: { // FNMADD.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); - const double rs3 = sourceRegValues[2].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); + const double rs3 = srcRegVals[2].get(); results[0] = RegisterValue(-(rs1 * rs2) - rs3, 8); }); @@ -1266,9 +1258,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_S: { // FNMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); - const float rs3 = checkNanBox(sourceRegValues[2]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); + const float rs3 = checkNanBox(srcRegVals[2]); // Some implementations return -NaN if certain inputs are NaN but spec // requires +NaN. Ensure this happens @@ -1284,7 +1276,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_L: { // FCVT.D.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1294,7 +1286,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_W: { // FCVT.D.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1304,7 +1296,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_L: { // FCVT.S.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = sourceRegValues[0].get(); + const int64_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1314,7 +1306,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_W: { // FCVT.S.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = sourceRegValues[0].get(); + const int32_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1324,7 +1316,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_D: { // FCVT.W.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1338,7 +1330,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_S: { // FCVT.W.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1352,7 +1344,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_D: { // FCVT.L.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1366,7 +1358,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_S: { // FCVT.L.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1380,7 +1372,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_D: { // FCVT.WU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1399,7 +1391,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_S: { // FCVT.WU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1418,7 +1410,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_D: { // FCVT.LU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1437,7 +1429,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_S: { // FCVT.LU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1456,7 +1448,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_LU: { // FCVT.D.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1466,7 +1458,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_WU: { // FCVT.D.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1476,7 +1468,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_LU: { // FCVT.S.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1486,7 +1478,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_WU: { // FCVT.S.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = sourceRegValues[0].get(); + const uint32_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1495,50 +1487,50 @@ void Instruction::execute() { } case Opcode::RISCV_FCVT_D_S: { // FCVT.D.S rd,rs1 - const float rs1 = checkNanBox(sourceRegValues[0]); + const float rs1 = checkNanBox(srcRegVals[0]); results[0] = RegisterValue((double)rs1, 8); break; } case Opcode::RISCV_FCVT_S_D: { // FCVT.S.D rd,rs1 - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } case Opcode::RISCV_FSGNJ_D: { // FSGNJ.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(std::copysign(rs1, rs2), 8); break; } case Opcode::RISCV_FSGNJ_S: { // FSGNJ.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, rs2)), 8); break; } case Opcode::RISCV_FSGNJN_D: { // FSGNJN.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); break; } case Opcode::RISCV_FSGNJN_S: { // FSGNJN.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, -rs2)), 8); break; } case Opcode::RISCV_FSGNJX_D: { // FSGNJX.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); const double xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1546,8 +1538,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FSGNJX_S: { // FSGNJX.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); const float xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1556,25 +1548,25 @@ void Instruction::execute() { } case Opcode::RISCV_FMV_D_X: { // FMV.D.X rd,rs1 - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_X_D: { // FMV.X.D rd,rs1 - const double rs1 = sourceRegValues[0].get(); + const double rs1 = srcRegVals[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_W_X: { // FMV.W.X rd,rs1 - const float rs1 = sourceRegValues[0].get(); + const float rs1 = srcRegVals[0].get(); results[0] = RegisterValue(NanBoxFloat(rs1), 8); break; } case Opcode::RISCV_FMV_X_W: { // FMV.X.W rd,rs1 - const uint64_t rs1 = sourceRegValues[0].get(); + const uint64_t rs1 = srcRegVals[0].get(); results[0] = RegisterValue(signExtendW(rs1), 8); break; @@ -1593,8 +1585,8 @@ void Instruction::execute() { // either input is a signaling NaN. Qemu doesn't seem to set CSR flags // with sNANs so unsure of correct implementation. Also require proper // Zicsr implementation - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1604,8 +1596,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FEQ_S: { // FEQ.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1615,8 +1607,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_D: { // FLT.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1629,8 +1621,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_S: { // FLT.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1643,8 +1635,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_D: { // FLE.D rd,rs1,rs2 - const double rs1 = sourceRegValues[0].get(); - const double rs2 = sourceRegValues[1].get(); + const double rs1 = srcRegVals[0].get(); + const double rs2 = srcRegVals[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1657,8 +1649,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_S: { // FLE.S rd,rs1,rs2 - const float rs1 = checkNanBox(sourceRegValues[0]); - const float rs2 = checkNanBox(sourceRegValues[1]); + const float rs1 = checkNanBox(srcRegVals[0]); + const float rs2 = checkNanBox(srcRegVals[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete From 5844ffc7422af478030095c175508b20b2049028 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 19 Jan 2024 12:51:05 +0000 Subject: [PATCH 052/115] Docs update --- .../developer/arch/supported/aarch64.rst | 22 +++++++++---------- .../sphinx/developer/arch/supported/riscv.rst | 4 ++-- src/include/simeng/arch/riscv/Instruction.hh | 4 ---- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 82454653a9..6673d884f1 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -122,17 +122,17 @@ The first step to add a new instruction (and the only, for many instructions) is There are several useful variables that execution behaviours have access to: -``operands`` +``srcRegVals`` .. _aarch64-adding-execution-behaviour-operands: - This is a vector of ``RegisterValue``, with each value corresponding to one of the input operands. For most instructions, ``operands[0]`` will be the *second* operand as written textually, as the first operand is typically the destination register. E.g., for the instruction ``add w0, w1, w2``, ``operands[0]`` will correspond to ``w1`` and ``[1]`` to ``w2``. + This is a vector of ``RegisterValue``, with each value corresponding to one of the input operands. For most instructions, ``srcRegVals[0]`` will be the *second* operand as written textually, as the first operand is typically the destination register. E.g., for the instruction ``add w0, w1, w2``, ``srcRegVals[0]`` will correspond to ``w1`` and ``[1]`` to ``w2``. - Some instructions have "implicit" register reads: these are added to the **start** of the operand array. E.g., the instruction ``b.ne #16`` implicitly reads the "NZCV" flags. In this case, ``operands[0]`` will be the value of the flag register. + Some instructions have "implicit" register reads: these are added to the **start** of the operand array. E.g., the instruction ``b.ne #16`` implicitly reads the "NZCV" flags. In this case, ``srcRegVals[0]`` will be the value of the flag register. - Some instructions have operands to which they both read and write, such as ``fmla v0.d, v1.d, v2.d`` both writing to *and* reading from ``v0.d``; in this case, ``operands[0]`` is ``v0.d``, and ``[1]`` and ``[2]`` are ``v1.d`` and ``v2.d`` respectively. + Some instructions have operands to which they both read and write, such as ``fmla v0.d, v1.d, v2.d`` both writing to *and* reading from ``v0.d``; in this case, ``srcRegVals[0]`` is ``v0.d``, and ``[1]`` and ``[2]`` are ``v1.d`` and ``v2.d`` respectively. - Instructions such as stores may not have any destination registers at all. In these cases, the ``operand`` indices match the positions as they appear: the first operand is ``[0]``, the second ``[1]``, and so on. + Instructions such as stores may not have any destination registers at all. In these cases, the ``srcRegVals`` indices match the positions as they appear: the first operand is ``[0]``, the second ``[1]``, and so on. ``results`` This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register. @@ -142,7 +142,7 @@ There are several useful variables that execution behaviours have access to: Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``. ``metadata`` - Each instruction stores a simplified form of the full disassembly metadata generated by Capstone. This is stored in the ``metadata`` member variable, and is of type ``InstructionMetadata``. The metadata object contains an ``metadata.operands`` array with entries corresponding to the textual operands of the instruction. **Note:** Unlike the instruction's ``operands`` member variable, ``metadata.operands`` entries correspond directly to their textual equivalent. For example, in the instruction ``add w0, w1, w2``, ``metadata.operands[0]`` will describe ``w0``, ``[1]`` describes ``w1``, and so on. + Each instruction stores a simplified form of the full disassembly metadata generated by Capstone. This is stored in the ``metadata`` member variable, and is of type ``InstructionMetadata``. The metadata object contains an ``metadata.operands`` array with entries corresponding to the textual operands of the instruction. **Note:** Unlike the instruction's ``srcRegVals`` member variable, ``metadata.operands`` entries correspond directly to their textual equivalent. For example, in the instruction ``add w0, w1, w2``, ``metadata.operands[0]`` will describe ``w0``, ``[1]`` describes ``w1``, and so on. The primary use for this data is to retrieve immediate values. For example, with the instruction ``add w0, w1, #1``, ``metadata.operands[2].imm`` would contain the value ``1``. Floating point immediates are similarly available, using ``.fp`` in place of ``.imm``. @@ -154,11 +154,11 @@ SimEng supports the Arm SVE extension and thus the use of ``Z`` vector registers Scalable Matrix Extension '''''''''''''''''''''''''' -Also supported is the Arm SME extension and thus the use of ``ZA`` sub-tile registers. The implementation of the ``ZA`` register is to treat each horizontal row the same as a vector register. Therefore, if a source operand is a sub-tile of ``ZA`` and contains 16 rows, then there will be 16 corresponding entries in the ``operands`` vector. Likewise, if a destination operand is ``ZA`` or a sub-tile of ``ZA`` then the ``results`` vector will require the corresponding number of horizontal rows. +Also supported is the Arm SME extension and thus the use of ``ZA`` sub-tile registers. The implementation of the ``ZA`` register is to treat each horizontal row the same as a vector register. Therefore, if a source operand is a sub-tile of ``ZA`` and contains 16 rows, then there will be 16 corresponding entries in the ``srcRegVals`` vector. Likewise, if a destination operand is ``ZA`` or a sub-tile of ``ZA`` then the ``results`` vector will require the corresponding number of horizontal rows. -SME instructions can also operate on sub-tile slices; individual rows or columns within a sub-tile. Regardless of whether a whole sub-tile or a slice is used as a source operand, all rows associated with said tile will be added to the ``operands`` vector. There are two reasons for this. First, the index value pointing to the relevant slice cannot be evaluated before instruction execution, thus, all sub-tile rows need to be provided. Second, if the source slice is a vertical slice (or a column of the sub-tile) then an element from each row is needed to construct the correct output. +SME instructions can also operate on sub-tile slices; individual rows or columns within a sub-tile. Regardless of whether a whole sub-tile or a slice is used as a source operand, all rows associated with said tile will be added to the ``srcRegVals`` vector. There are two reasons for this. First, the index value pointing to the relevant slice cannot be evaluated before instruction execution, thus, all sub-tile rows need to be provided. Second, if the source slice is a vertical slice (or a column of the sub-tile) then an element from each row is needed to construct the correct output. -Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``operands`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. +Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``srcRegVals`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. Before implementing any further SME functionality we highly recommend familiarising yourself with the specification; found `here `_. @@ -202,7 +202,7 @@ Capstone provides a ``cstool`` utility, which provides a visual representation o Zero registers ************** -AArch64 provides two zero registers, ``WZR`` and ``XZR``, which are always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``operands`` entry with a 0-value ``RegisterValue``. +AArch64 provides two zero registers, ``WZR`` and ``XZR``, which are always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``srcRegVals`` entry with a 0-value ``RegisterValue``. For instructions that are capable of generating multiple results (typically flag-setting instructions), they can claim to write to one of the zero registers: in these cases, the result is discarded. This implementation supports this behaviour, and reduces the number of available ``results`` entries accordingly. @@ -211,7 +211,7 @@ Loads and stores In addition to an execution behaviour, memory instructions also require a new entry in the address generation behaviour table found in ``src/lib/arch/aarch64/Instruction_address.cc``. These entries are responsible for describing the method used to generate the addresses that these instructions will read from or write to. -Address generation is expected to generate one or more instances of ``MemoryAccessTarget``, containing an address and the number of bytes to access. The same variables described above (``operands``, ``metadata``) are available to use to generate these addresses. +Address generation is expected to generate one or more instances of ``MemoryAccessTarget``, containing an address and the number of bytes to access. The same variables described above (``srcRegVals``, ``metadata``) are available to use to generate these addresses. Once the addresses have been generated, they should be supplied in a vector to the ``setMemoryAddresses`` helper function. diff --git a/docs/sphinx/developer/arch/supported/riscv.rst b/docs/sphinx/developer/arch/supported/riscv.rst index 7049093d68..aa07245574 100644 --- a/docs/sphinx/developer/arch/supported/riscv.rst +++ b/docs/sphinx/developer/arch/supported/riscv.rst @@ -60,7 +60,7 @@ The process for adding a new instruction is very similar to that of :ref:`AArch6 Zero registers ************** -RISC-V provides a zero register ``RO`` which is always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``operands`` entry with a 0-value ``RegisterValue``. +RISC-V provides a zero register ``RO`` which is always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``srcRegVals`` entry with a 0-value ``RegisterValue``. For instructions that write to the zero registers, the result is discarded. The number of available ``results`` entries is reduced accordingly. @@ -69,7 +69,7 @@ Loads and stores In addition to an execution behaviour, memory instructions also require a new entry in the address generation behaviour table found in ``src/lib/arch/riscv/Instruction_address.cc``. These entries are responsible for describing the method used to generate the addresses that these instructions will read from or write to. -Address generation is expected to generate one or more instances of ``MemoryAddressTarget``, containing an address and the number of bytes to access. The same variables as described in the :ref:`AArch64 documentation ` (``operands``, ``metadata``) are available to use to generate these addresses. +Address generation is expected to generate one or more instances of ``MemoryAddressTarget``, containing an address and the number of bytes to access. The same variables as described in the :ref:`AArch64 documentation ` (``srcRegVals``, ``metadata``) are available to use to generate these addresses. Once the addresses have been generated, they should be supplied in a vector to the ``setMemoryAddresses`` helper function. diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 3c34e71ba4..4a6a8dd03f 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -198,10 +198,6 @@ class Instruction : public simeng::Instruction { /** An array of provided operand values. Each entry corresponds to a * `sourceRegisters` entry. */ - // TODO this name change requires updates of the docs on approval - // developer/arch/supported/aarch64.html#aarch64-adding-execution-behaviour-operands - // TODO update AArch64 to keep both in line and references in docs from RISC-V - // to AArch64 correct std::array srcRegVals; /** Extracted value of current immediate from metadata */ From 08dbf0ad720eb918e15c229391505944646d4142 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 19 Jan 2024 13:33:53 +0000 Subject: [PATCH 053/115] Change name operandsPending for clarity --- .../simeng/arch/aarch64/Instruction.hh | 6 ++--- src/include/simeng/arch/riscv/Instruction.hh | 6 ++--- src/lib/arch/aarch64/Instruction.cc | 4 ++-- src/lib/arch/aarch64/Instruction_decode.cc | 22 +++++++++---------- src/lib/arch/riscv/Instruction.cc | 4 ++-- src/lib/arch/riscv/Instruction_decode.cc | 6 ++--- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 1203a119fc..a321acc815 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -414,9 +414,9 @@ class Instruction : public simeng::Instruction { void setDestinationRegisters(const std::vector& registers); // Scheduling - /** The number of operands that have not yet had values supplied. Used to - * determine execution readiness. */ - short operandsPending = 0; + /** The number of source operands that have not yet had values supplied. Used + * to determine execution readiness. */ + short numSrcOpsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 4a6a8dd03f..7e499a3602 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -216,9 +216,9 @@ class Instruction : public simeng::Instruction { void decode(); // Scheduling - /** The number of operands that have not yet had values supplied. Used to - * determine execution readiness. */ - uint16_t numSourceOperandsPending = 0; + /** The number of source operands that have not yet had values supplied. Used + * to determine execution readiness. */ + uint16_t numSrcOpsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index 096216e686..511f55cb21 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -66,7 +66,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { "Attempted to provide an uninitialised RegisterValue"); srcRegVals[i] = value; - operandsPending--; + numSrcOpsPending--; } void Instruction::supplyData(uint64_t address, const RegisterValue& data) { @@ -92,7 +92,7 @@ span Instruction::getData() const { return {memoryData.data(), memoryData.size()}; } -bool Instruction::canExecute() const { return (operandsPending == 0); } +bool Instruction::canExecute() const { return (numSrcOpsPending == 0); } const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 4cb82cdac0..95eb704d03 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -196,7 +196,7 @@ void Instruction::decode() { for (size_t i = 0; i < metadata.implicitSourceCount; i++) { sourceRegisters.push_back( csRegToRegister(static_cast(metadata.implicitSources[i]))); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; } @@ -239,7 +239,7 @@ void Instruction::decode() { // unaltered row values sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - operandsPending++; + numSrcOpsPending++; } } else { // Add register writes to destinations, but skip zero-register @@ -257,12 +257,12 @@ void Instruction::decode() { for (int i = 0; i < regs.size(); i++) { sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - operandsPending++; + numSrcOpsPending++; } } else { // Add register reads to destinations sourceRegisters.push_back(csRegToRegister(op.reg)); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; } if (op.shift.value > 0) isNoShift_ = false; // Identify shift operands @@ -270,7 +270,7 @@ void Instruction::decode() { } else if (op.type == ARM64_OP_MEM) { // Memory operand accessesMemory = true; sourceRegisters.push_back(csRegToRegister(op.mem.base)); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; if (metadata.writeback) { @@ -281,7 +281,7 @@ void Instruction::decode() { if (op.mem.index) { // Register offset; add to sources sourceRegisters.push_back(csRegToRegister(op.mem.index)); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; } } else if (op.type == ARM64_OP_SME_INDEX) { // SME instruction with index @@ -298,7 +298,7 @@ void Instruction::decode() { for (int i = 0; i < regs.size(); i++) { sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - operandsPending++; + numSrcOpsPending++; if (op.access & cs_ac_type::CS_AC_WRITE) { destinationRegisters.push_back(regs[i]); destinationRegisterCount++; @@ -313,13 +313,13 @@ void Instruction::decode() { destinationRegisterCount++; } else if (op.access & cs_ac_type::CS_AC_READ) { sourceRegisters.push_back(csRegToRegister(op.sme_index.reg)); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; } } // Register that is base of index will always be a source operand sourceRegisters.push_back(csRegToRegister(op.sme_index.base)); - operandsPending++; + numSrcOpsPending++; sourceRegisterCount++; } else if (op.type == ARM64_OP_REG_MRS) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); @@ -333,7 +333,7 @@ void Instruction::decode() { sourceRegisters.push_back( {RegisterType::SYSTEM, static_cast(sysRegTag)}); sourceRegisterCount++; - operandsPending++; + numSrcOpsPending++; } } else if (op.type == ARM64_OP_REG_MSR) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); @@ -646,7 +646,7 @@ void Instruction::decode() { for (uint16_t i = 0; i < sourceRegisterCount; i++) { if (sourceRegisters[i] == Instruction::ZERO_REGISTER) { srcRegVals[i] = RegisterValue(0, 8); - operandsPending--; + numSrcOpsPending--; } } } diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 7e8afdd08f..8ed8fc4976 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -62,7 +62,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { "Attempted to provide an uninitialised RegisterValue"); srcRegVals[i] = value; - numSourceOperandsPending--; + numSrcOpsPending--; } void Instruction::supplyData(uint64_t address, const RegisterValue& data) { @@ -88,7 +88,7 @@ span Instruction::getData() const { return {memoryData.data(), memoryData.size()}; } -bool Instruction::canExecute() const { return (numSourceOperandsPending == 0); } +bool Instruction::canExecute() const { return (numSrcOpsPending == 0); } const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 867049ca59..ef88260675 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -152,7 +152,7 @@ void Instruction::decode() { // Catch zero register references and pre-complete those operands srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); } else { - numSourceOperandsPending++; + numSrcOpsPending++; } sourceRegisterCount++; @@ -194,7 +194,7 @@ void Instruction::decode() { // Catch zero register references and pre-complete those operands srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); } else { - numSourceOperandsPending++; + numSrcOpsPending++; } sourceRegisterCount++; @@ -207,7 +207,7 @@ void Instruction::decode() { sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); imm = op.mem.disp; sourceRegisterCount++; - numSourceOperandsPending++; + numSrcOpsPending++; } // First operands never immediate From 95f86f7468bdbbcc2658c287a06511557987d820 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 19 Jan 2024 13:37:44 +0000 Subject: [PATCH 054/115] Add comment --- src/lib/arch/riscv/InstructionMetadata.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/arch/riscv/InstructionMetadata.hh b/src/lib/arch/riscv/InstructionMetadata.hh index 7904289c2a..ef8705b990 100644 --- a/src/lib/arch/riscv/InstructionMetadata.hh +++ b/src/lib/arch/riscv/InstructionMetadata.hh @@ -89,6 +89,8 @@ struct InstructionMetadata { /** The instruction length for variable instruction length support. */ INSTR_LENGTH len; + + /** The length of the instruction encoding in bytes. */ uint8_t lenBytes; private: From 4d5df218cbdaff46c2c25c75175d3fa4f118d749 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 19 Jan 2024 13:40:48 +0000 Subject: [PATCH 055/115] Update type --- src/include/simeng/arch/aarch64/Instruction.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index a321acc815..65ac48d6b2 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -416,7 +416,7 @@ class Instruction : public simeng::Instruction { // Scheduling /** The number of source operands that have not yet had values supplied. Used * to determine execution readiness. */ - short numSrcOpsPending = 0; + uint16_t numSrcOpsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ From 000fe93c4eb895550cb6ea3fd6c68332cc9f7f31 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 26 Jan 2024 14:59:59 +0000 Subject: [PATCH 056/115] Undo operands renaming --- .../simeng/arch/aarch64/Instruction.hh | 2 +- src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/aarch64/Instruction.cc | 6 +- src/lib/arch/aarch64/Instruction_address.cc | 517 ++--- src/lib/arch/aarch64/Instruction_decode.cc | 4 +- src/lib/arch/aarch64/Instruction_execute.cc | 1995 ++++++++--------- src/lib/arch/riscv/Instruction.cc | 6 +- src/lib/arch/riscv/Instruction_address.cc | 18 +- src/lib/arch/riscv/Instruction_decode.cc | 4 +- src/lib/arch/riscv/Instruction_execute.cc | 396 ++-- 10 files changed, 1433 insertions(+), 1517 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 65ac48d6b2..79d1115dbf 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -390,7 +390,7 @@ class Instruction : public simeng::Instruction { /** A vector of provided operand values. Each entry corresponds to a * `sourceRegisters` entry. */ - std::vector srcRegVals; + std::vector operands; /** A vector of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 7e499a3602..8c44af6c9c 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -198,7 +198,7 @@ class Instruction : public simeng::Instruction { /** An array of provided operand values. Each entry corresponds to a * `sourceRegisters` entry. */ - std::array srcRegVals; + std::array operands; /** Extracted value of current immediate from metadata */ int64_t imm = 0; diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index 511f55cb21..a8fbf6706c 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -41,7 +41,7 @@ const span Instruction::getSourceRegisters() const { } const span Instruction::getSourceOperands() const { - return {const_cast(srcRegVals.data()), srcRegVals.size()}; + return {const_cast(operands.data()), operands.size()}; } const span Instruction::getDestinationRegisters() const { @@ -49,7 +49,7 @@ const span Instruction::getDestinationRegisters() const { destinationRegisterCount}; } bool Instruction::isOperandReady(int index) const { - return static_cast(srcRegVals[index]); + return static_cast(operands[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { @@ -65,7 +65,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { assert(value.size() > 0 && "Attempted to provide an uninitialised RegisterValue"); - srcRegVals[i] = value; + operands[i] = value; numSrcOpsPending--; } diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index e94d7f4a7a..3878d80648 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -52,7 +52,7 @@ span Instruction::generateAddresses() { case MicroOpcode::LDR_ADDR: { std::vector addresses; generateContiguousAddresses( - srcRegVals[0].get() + metadata.operands[1].mem.disp, 1, + operands[0].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); @@ -61,7 +61,7 @@ span Instruction::generateAddresses() { case MicroOpcode::STR_ADDR: { std::vector addresses; generateContiguousAddresses( - srcRegVals[0].get() + metadata.operands[0].mem.disp, 1, + operands[0].get() + metadata.operands[0].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); @@ -82,11 +82,11 @@ span Instruction::generateAddresses() { : architecture_.getVectorLength(); switch (metadata.opcode) { case Opcode::AArch64_CASALW: { // casal ws, wt, [xn|sp] - setMemoryAddresses({{srcRegVals[2].get(), 4}}); + setMemoryAddresses({{operands[2].get(), 4}}); break; } case Opcode::AArch64_CASALX: { // casal xs, xt, [xn|sp] - setMemoryAddresses({{srcRegVals[2].get(), 8}}); + setMemoryAddresses({{operands[2].get(), 8}}); break; } case Opcode::AArch64_LD1_MXIPXX_V_D: // ld1d {zatv.d[ws, #imm]}, pg/z, @@ -95,10 +95,10 @@ span Instruction::generateAddresses() { // [{, xm, lsl #3}] // SME const uint16_t partition_num = VL_bits / 64; - const uint64_t n = srcRegVals[partition_num + 2].get(); + const uint64_t n = operands[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = srcRegVals[partition_num + 3].get() << 3; + m = operands[partition_num + 3].get() << 3; setMemoryAddresses({(n + m), static_cast(VL_bits / 8)}); break; } @@ -108,31 +108,31 @@ span Instruction::generateAddresses() { // [{, xm, LSL #2}] // SME const uint16_t partition_num = VL_bits / 32; - const uint64_t n = srcRegVals[partition_num + 2].get(); + const uint64_t n = operands[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = srcRegVals[partition_num + 3].get() << 2; + m = operands[partition_num + 3].get() << 2; setMemoryAddresses({(n + m), static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1i32: { // ld1 {vt.s}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_LD1i64: { // ld1 {vt.d}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } case Opcode::AArch64_LD1i64_POST: { // ld1 {vt.d}[index], [xn], #8 - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[2].mem.disp, + {{operands[1].get() + metadata.operands[2].mem.disp, 8}}); break; } @@ -141,28 +141,28 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD1RQ_D_IMM: { // ld1rqd {zd.d}, pg/z, [xn{, #imm}] uint64_t addr = - srcRegVals[1].get() + metadata.operands[2].mem.disp; + operands[1].get() + metadata.operands[2].mem.disp; setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RQ_W: { // ld1rqw {zd.s}, pg/z, [xn, xm, lsl #2] uint64_t addr = - srcRegVals[1].get() + (srcRegVals[2].get() * 4); + operands[1].get() + (operands[2].get() * 4); setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RQ_W_IMM: { // ld1rqw {zd.s}, pg/z, [xn{, #imm}] uint64_t addr = - srcRegVals[1].get() + metadata.operands[2].mem.disp; + operands[1].get() + metadata.operands[2].mem.disp; setMemoryAddresses({addr, static_cast(16)}); break; } case Opcode::AArch64_LD1RW_IMM: { // ld1rw {zt.s}, pg/z, [xn, #imm] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[2].mem.disp, + {{operands[1].get() + metadata.operands[2].mem.disp, 4}}); break; } @@ -170,75 +170,75 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1Rv16b: { // ld1r {vt.16b}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv16b_POST: { // ld1r {vt.16b}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv1d: { // ld1r {vt.1d}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv1d_POST: { // ld1r {vt.1d}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv2d: { // ld1r {vt.2d}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2d_POST: { // ld1r {vt.2d}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2s: { // ld1r {vt.2s}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv2s_POST: { // ld1r {vt.2s}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv4h: { // ld1r {vt.4h}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv4h_POST: { // ld1r {vt.4h}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8b: { // ld1r {vt.8b}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8b_POST: { // ld1r {vt.8b}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LD1Rv8h: { // ld1r {vt.8h}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv8h_POST: { // ld1r {vt.8h}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv4s: { // ld1r {vt.4s}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Rv4s_POST: { // ld1r {vt.4s}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Onev16b: { // ld1 {vt.16b}, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Onev16b_POST: { // ld1 {vt.16b}, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 16}}); + setMemoryAddresses({{operands[0].get(), 16}}); break; } case Opcode::AArch64_LD1Fourv16b: // ld1 {vt1.16b, vt2.16b, vt3.16b, @@ -258,7 +258,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_LD1Fourv4s_POST: { // ld1 {vt1.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> - uint64_t base = srcRegVals[0].get(); + uint64_t base = operands[0].get(); setMemoryAddresses( {{base, 16}, {base + 16, 16}, {base + 32, 16}, {base + 48, 16}}); break; @@ -277,20 +277,20 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_LD1Twov4s_POST: { // ld1 {vt1.4s, vt2.4s}, [xn], // <#imm|xm> - uint64_t base = srcRegVals[0].get(); + uint64_t base = operands[0].get(); setMemoryAddresses({{base, 16}, {base + 16, 16}}); break; } case Opcode::AArch64_LD1B: { // ld1b {zt.b}, pg/z, [xn, xm] - const uint64_t base = srcRegVals[1].get(); - const uint64_t offset = srcRegVals[2].get(); + const uint64_t base = operands[1].get(); + const uint64_t offset = operands[2].get(); setMemoryAddresses({base + offset, static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, // mul vl}] - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); uint64_t addr = base + (offset * (VL_bits / 8)); @@ -299,8 +299,8 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1D: { // ld1d {zt.d}, pg/z, [xn, xm, lsl #3] - const uint64_t base = srcRegVals[1].get(); - const uint64_t offset = srcRegVals[2].get(); + const uint64_t base = operands[1].get(); + const uint64_t offset = operands[2].get(); const uint64_t addr = base + (offset * 8); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); @@ -310,7 +310,7 @@ span Instruction::generateAddresses() { // mul vl}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const uint64_t offset = static_cast(metadata.operands[2].mem.disp); const uint64_t addr = base + (offset * partition_num * 8); @@ -319,16 +319,16 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_LD1H: { // ld1h {zt.h}, pg/z, [xn, xm, lsl #1] - const uint64_t base = srcRegVals[1].get(); - const uint64_t offset = srcRegVals[2].get(); + const uint64_t base = operands[1].get(); + const uint64_t offset = operands[2].get(); const uint64_t addr = base + (offset * 2); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] - const uint64_t base = srcRegVals[1].get(); - const uint64_t offset = srcRegVals[2].get(); + const uint64_t base = operands[1].get(); + const uint64_t offset = operands[2].get(); const uint64_t addr = base + (offset * 4); setMemoryAddresses({addr, static_cast(VL_bits / 8)}); @@ -338,7 +338,7 @@ span Instruction::generateAddresses() { // mul vl}] const uint16_t partition_num = VL_bits / 32; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); const uint64_t addr = base + (offset * partition_num * 4); @@ -348,8 +348,8 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD2D: { // ld2d {zt1.d, zt2.d}, pg/z, [xn|sp, xm, // lsl #3] - const uint64_t base = srcRegVals[1].get(); - uint64_t offset = srcRegVals[2].get(); + const uint64_t base = operands[1].get(); + uint64_t offset = operands[2].get(); std::vector addresses; addresses.reserve(2); @@ -366,7 +366,7 @@ span Instruction::generateAddresses() { // [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[3].mem.disp); std::vector addresses; @@ -385,7 +385,7 @@ span Instruction::generateAddresses() { // [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[4].mem.disp); std::vector addresses; @@ -405,7 +405,7 @@ span Instruction::generateAddresses() { // pg/z, [xn|sp{, #imm, MUL VL}] const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[5].mem.disp); std::vector addresses; @@ -427,76 +427,74 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD2Twov4s_POST: { // ld2 {vt1.4s, vt2.4s}, [xn], // #imm - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); setMemoryAddresses({{base, 16}, {base + 16, 16}}); break; } case Opcode::AArch64_LDADDLW: // ldaddl ws, wt, [xn] [[fallthrough]]; case Opcode::AArch64_LDADDW: { // ldadd ws, wt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_LDARB: { // ldarb wt, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 1}}); + setMemoryAddresses({{operands[0].get(), 1}}); break; } case Opcode::AArch64_LDARW: { // ldar wt, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 4}}); + setMemoryAddresses({{operands[0].get(), 4}}); break; } case Opcode::AArch64_LDARX: { // ldar xt, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LDAXRW: { // ldaxr wd, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 4}}); + setMemoryAddresses({{operands[0].get(), 4}}); break; } case Opcode::AArch64_LDAXRX: { // ldaxr xd, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_LDRBBpost: { // ldrb wt, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 1}}); + setMemoryAddresses({{operands[0].get(), 1}}); break; } case Opcode::AArch64_LDRBBpre: { // ldrb wt, [xn, #imm]! setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_LDRBBroW: { // ldrb wt, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRBBroX: { // ldrb wt, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRBBui: { // ldrb wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_LDRDroW: { // ldr dt, [xn, wm{, extend {amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRDroX: { // ldr dt, [xn, xm{, extend {amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRBui: // ldr bt, [xn, #imm] @@ -515,7 +513,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDRXpre: { // ldr xt, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - srcRegVals[0].get() + metadata.operands[1].mem.disp, 1, + operands[0].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -528,55 +526,53 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDRWpost: // ldr wt, [xn], #imm case Opcode::AArch64_LDRXpost: { // ldr xt, [xn], #imm std::vector addresses; - generateContiguousAddresses(srcRegVals[0].get(), 1, dataSize_, + generateContiguousAddresses(operands[0].get(), 1, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_LDRHHpost: { // ldrh wt, [xn], #imm - setMemoryAddresses({{srcRegVals[0].get(), 2}}); + setMemoryAddresses({{operands[0].get(), 2}}); break; } case Opcode::AArch64_LDRHHpre: { // ldrh wt, [xn, #imm]! setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_LDRHHroW: { // ldrh wt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRHHroX: { // ldrh wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRHHui: { // ldrh wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_LDRQroX: { // ldr qt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 16}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 16}}); break; } case Opcode::AArch64_LDRSroW: { // ldr st, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSroX: { // ldr st, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSWl: { // ldrsw xt, #imm @@ -586,14 +582,14 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDRWroW: { // ldr wt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRWroX: { // ldr wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRXl: { // ldr xt, #imm @@ -603,21 +599,21 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDRXroW: { // ldr xt, [xn, wn{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDRXroX: { // ldr xt, [xn, xn{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 8}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 8}}); break; } case Opcode::AArch64_LDR_PXI: { // ldr pt, [xn{, #imm, mul vl}] const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint64_t base = srcRegVals[0].get(); + const uint64_t base = operands[0].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -629,7 +625,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDR_ZXI: { // ldr zt, [xn{, #imm, mul vl}] const uint16_t partition_num = VL_bits / 8; - const uint64_t base = srcRegVals[0].get(); + const uint64_t base = operands[0].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); const uint64_t addr = base + (offset * partition_num); @@ -639,7 +635,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDNPSi: { // ldnp st1, st2, [xn, #imm] uint64_t base = - srcRegVals[0].get() + metadata.operands[2].mem.disp; + operands[0].get() + metadata.operands[2].mem.disp; setMemoryAddresses({{base, 4}, {base + 4, 4}}); break; } @@ -655,7 +651,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDPXpre: { // ldp xt1, xt2, [xn, #imm!] std::vector addresses; generateContiguousAddresses( - srcRegVals[0].get() + metadata.operands[2].mem.disp, 2, + operands[0].get() + metadata.operands[2].mem.disp, 2, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -666,147 +662,136 @@ span Instruction::generateAddresses() { case Opcode::AArch64_LDPWpost: // ldp wt1, wt2, [xn], #imm case Opcode::AArch64_LDPXpost: { // ldp xt1, xt2, [xn], #imm std::vector addresses; - generateContiguousAddresses(srcRegVals[0].get(), 2, dataSize_, + generateContiguousAddresses(operands[0].get(), 2, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_LDPSWi: { // ldpsw xt1, xt2, [xn {, #imm}] uint64_t base = - srcRegVals[0].get() + metadata.operands[2].mem.disp; + operands[0].get() + metadata.operands[2].mem.disp; setMemoryAddresses({{base, 4}, {base + 4, 4}}); break; } case Opcode::AArch64_LDRSBWroX: { // ldrsb wt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 1}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 1}}); break; } case Opcode::AArch64_LDRSBWui: { // ldrsb xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_LDRSBXui: { // ldrsb xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_LDRSHWroW: { // ldrsh wt, [xn, wm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHWroX: { // ldrsh wt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHWui: { // ldrsh wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_LDRSHXroW: { // ldrsh xt, [xn, wm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHXroX: { // ldrsh xt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 2}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 2}}); break; } case Opcode::AArch64_LDRSHXui: { // ldrsh xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_LDRSWpost: { // ldrsw xt, [xn], #simm - setMemoryAddresses({{srcRegVals[0].get(), 4}}); + setMemoryAddresses({{operands[0].get(), 4}}); break; } case Opcode::AArch64_LDRSWroX: { // ldrsw xt, [xn, xm{, extend // {#amount}}] uint64_t offset = - extendOffset(srcRegVals[1].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[0].get() + offset, 4}}); + extendOffset(operands[1].get(), metadata.operands[1]); + setMemoryAddresses({{operands[0].get() + offset, 4}}); break; } case Opcode::AArch64_LDRSWui: { // ldrsw xt, [xn{, #pimm}] uint64_t base = - srcRegVals[0].get() + metadata.operands[1].mem.disp; + operands[0].get() + metadata.operands[1].mem.disp; setMemoryAddresses({{base, 4}}); break; } case Opcode::AArch64_LDURBBi: { // ldurb wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_LDURDi: { // ldur dt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 8}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 8}}); break; } case Opcode::AArch64_LDURHHi: { // ldurh wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_LDURQi: { // ldur qt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, + {{operands[0].get() + metadata.operands[1].mem.disp, 16}}); break; } case Opcode::AArch64_LDURSWi: { // ldursw xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 4}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); break; } case Opcode::AArch64_LDURSi: { // ldur sd, [{, #imm}] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 4}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); break; } case Opcode::AArch64_LDURWi: { // ldur wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 4}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 4}}); break; } case Opcode::AArch64_LDURXi: { // ldur xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[0].get() + metadata.operands[1].mem.disp, - 8}}); + {{operands[0].get() + metadata.operands[1].mem.disp, 8}}); break; } case Opcode::AArch64_LDXRW: { // ldxr wt, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 4}}); + setMemoryAddresses({{operands[0].get(), 4}}); break; } case Opcode::AArch64_LDXRX: { // ldxr xt, [xn] - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::AArch64_PRFMui: { // prfm op, [xn, xm{, extend {#amount}}] @@ -814,11 +799,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1B: { // st1b {zt.b}, pg, [xn, xm] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 8; - const uint64_t base = srcRegVals[2].get(); - const uint64_t offset = srcRegVals[3].get(); + const uint64_t base = operands[2].get(); + const uint64_t offset = operands[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -829,10 +814,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1B_IMM: { // st1b {zt.b}, pg, [xn{, #imm, mul vl}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 8; - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -846,11 +831,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); - const uint64_t* offset = srcRegVals[3].getAsVector(); + const uint64_t base = operands[2].get(); + const uint64_t* offset = operands[3].getAsVector(); std::vector addresses; @@ -865,11 +850,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); - const uint64_t* offset = srcRegVals[3].getAsVector(); + const uint64_t base = operands[2].get(); + const uint64_t* offset = operands[3].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -886,11 +871,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { // st1d {zt.d}, pg, [xn, // zm.d, lsl #3] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); - const uint64_t* offset = srcRegVals[3].getAsVector(); + const uint64_t base = operands[2].get(); + const uint64_t* offset = operands[3].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -906,11 +891,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1D: { // st1d {zt.d}, pg, [xn, xm, lsl #3] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); - const uint64_t offset = srcRegVals[3].get(); + const uint64_t base = operands[2].get(); + const uint64_t offset = operands[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -921,10 +906,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1D_IMM: { // st1d {zt.d}, pg, [xn{, #imm, mul vl}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -939,10 +924,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST2D_IMM: { // st2d {zt1.d, zt2.d}, pg, [{, // #imm, mul vl}] - const uint64_t* p = srcRegVals[2].getAsVector(); + const uint64_t* p = operands[2].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[3].get(); + const uint64_t base = operands[3].get(); const int64_t offset = static_cast(metadata.operands[3].mem.disp); @@ -963,11 +948,11 @@ span Instruction::generateAddresses() { // SME const uint16_t partition_num = VL_bits / 64; const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); - const uint64_t n = srcRegVals[partition_num + 2].get(); + operands[partition_num + 1].getAsVector(); + const uint64_t n = operands[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = srcRegVals[partition_num + 3].get() << 3; + m = operands[partition_num + 3].get() << 3; std::vector addresses; addresses.reserve(partition_num); @@ -984,11 +969,11 @@ span Instruction::generateAddresses() { // SME const uint16_t partition_num = VL_bits / 32; const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); - const uint64_t n = srcRegVals[partition_num + 2].get(); + operands[partition_num + 1].getAsVector(); + const uint64_t n = operands[partition_num + 2].get(); uint64_t m = 0; if (metadata.operands[2].mem.index) - m = srcRegVals[partition_num + 3].get() << 2; + m = operands[partition_num + 3].get() << 2; std::vector addresses; addresses.reserve(partition_num); @@ -999,11 +984,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1W: { // st1w {zt.s}, pg, [xn, xm, lsl #2] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t base = srcRegVals[2].get(); - const uint64_t offset = srcRegVals[3].get(); + const uint64_t base = operands[2].get(); + const uint64_t offset = operands[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -1014,11 +999,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_ST1W_D: { // st1w {zt.d}, pg, [xn, xm, lsl #2] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[2].get(); - const uint64_t offset = srcRegVals[3].get(); + const uint64_t base = operands[2].get(); + const uint64_t offset = operands[3].get(); std::vector addresses; addresses.reserve(partition_num); @@ -1030,10 +1015,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST1W_IMM: { // st1w {zt.s}, pg, [xn{, #imm, mul // vl}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1047,10 +1032,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1W_D_IMM: { // st1w {zt.d}, pg, [zn.d{, #imm}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = srcRegVals[2].getAsVector(); + const uint64_t* n = operands[2].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1068,10 +1053,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1W_IMM: { // st1w {zt.s}, pg, [zn.s{, #imm}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint32_t* n = srcRegVals[2].getAsVector(); + const uint32_t* n = operands[2].getAsVector(); const int64_t offset = static_cast( static_cast(metadata.operands[2].mem.disp)); @@ -1089,11 +1074,11 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_GLD1D_REAL: { // ld1d {zt.d}, pg/z, [xn, zm.d] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); - const uint64_t* offset = srcRegVals[2].getAsVector(); + const uint64_t base = operands[1].get(); + const uint64_t* offset = operands[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1110,11 +1095,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, // zm.d, LSL #3] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t base = srcRegVals[1].get(); - const uint64_t* offset = srcRegVals[2].getAsVector(); + const uint64_t base = operands[1].get(); + const uint64_t* offset = operands[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1131,10 +1116,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, // #imm}] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = srcRegVals[1].getAsVector(); + const uint64_t* n = operands[1].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1153,10 +1138,10 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, // [zn.d{, #imm}] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = srcRegVals[1].getAsVector(); + const uint64_t* n = operands[1].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1175,11 +1160,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, // [, zm.d, lsl #2] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t n = srcRegVals[1].get(); - const uint64_t* m = srcRegVals[2].getAsVector(); + const uint64_t n = operands[1].get(); + const uint64_t* m = operands[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1196,11 +1181,11 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, // [, zm.s, sxtw] - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; - const uint64_t n = srcRegVals[1].get(); - const uint32_t* m = srcRegVals[2].getAsVector(); + const uint64_t n = operands[1].get(); + const uint32_t* m = operands[2].getAsVector(); std::vector addresses; addresses.reserve(partition_num); @@ -1216,10 +1201,10 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_SST1D_IMM: { // st1d {zt.d}, pg, [zn.d{, #imm}] - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; - const uint64_t* n = srcRegVals[2].getAsVector(); + const uint64_t* n = operands[2].getAsVector(); const int64_t offset = static_cast(metadata.operands[2].mem.disp); @@ -1238,7 +1223,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_ST1Fourv2s_POST: { // st1 {vt.2s, vt2.2s, vt3.2s, // vt4.2s}, [xn], <#imm|xm> - const uint64_t base = srcRegVals[4].get(); + const uint64_t base = operands[4].get(); std::vector addresses; addresses.reserve(4); @@ -1265,7 +1250,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_ST1Fourv4s_POST: { // st1 {vt.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> - const uint64_t base = srcRegVals[4].get(); + const uint64_t base = operands[4].get(); std::vector addresses; addresses.reserve(4); @@ -1289,7 +1274,7 @@ span Instruction::generateAddresses() { [[fallthrough]]; case Opcode::AArch64_ST1Twov4s_POST: { // st1 {vt.4s, vt2.4s}, [xn], // <#imm|xm> - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); std::vector addresses; addresses.reserve(2); @@ -1302,30 +1287,30 @@ span Instruction::generateAddresses() { case Opcode::AArch64_ST1i8_POST: [[fallthrough]]; case Opcode::AArch64_ST1i8: { // st1 {vt.b}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 1}}); + setMemoryAddresses({{operands[1].get(), 1}}); break; } case Opcode::AArch64_ST1i16_POST: [[fallthrough]]; case Opcode::AArch64_ST1i16: { // st1 {vt.h}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 2}}); + setMemoryAddresses({{operands[1].get(), 2}}); break; } case Opcode::AArch64_ST1i32_POST: [[fallthrough]]; case Opcode::AArch64_ST1i32: { // st1 {vt.s}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_ST1i64_POST: [[fallthrough]]; case Opcode::AArch64_ST1i64: { // st1 {vt.d}[index], [xn] - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } case Opcode::AArch64_ST2Twov4s_POST: { // st2 {vt1.4s, vt2.4s}, [xn], // #imm - const uint64_t base = srcRegVals[2].get(); + const uint64_t base = operands[2].get(); std::vector addresses; addresses.reserve(2); @@ -1337,23 +1322,23 @@ span Instruction::generateAddresses() { break; } case Opcode::AArch64_STLRB: { // stlrb wt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 1}}); + setMemoryAddresses({{operands[1].get(), 1}}); break; } case Opcode::AArch64_STLRW: { // stlr wt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_STLRX: { // stlr xt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } case Opcode::AArch64_STLXRW: { // stlxr ws, wt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_STLXRX: { // stlxr ws, xt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } case Opcode::AArch64_STPDi: // stp dt1, dt2, [xn, #imm] @@ -1368,7 +1353,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STPXpre: { // stp xt1, xt2, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - srcRegVals[2].get() + metadata.operands[2].mem.disp, 2, + operands[2].get() + metadata.operands[2].mem.disp, 2, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -1379,51 +1364,49 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STPWpost: // stp wt1, wt2, [xn], #imm case Opcode::AArch64_STPXpost: { // stp xt1, xt2, [xn], #imm std::vector addresses; - generateContiguousAddresses(srcRegVals[2].get(), 2, dataSize_, + generateContiguousAddresses(operands[2].get(), 2, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_STRBBpost: { // strb wd, [xn], #imm - setMemoryAddresses({{srcRegVals[1].get(), 1}}); + setMemoryAddresses({{operands[1].get(), 1}}); break; } case Opcode::AArch64_STRBBpre: { // strb wd, [xn, #imm]! setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_STRBBroW: { // strb wd, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 1}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 1}}); break; } case Opcode::AArch64_STRBBroX: { // strb wd, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 1}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 1}}); break; } case Opcode::AArch64_STRBBui: { // strb wd, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_STRDroW: { // str dt, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRDroX: { // str dt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRBui: // str bt, [xn, #imm] @@ -1442,7 +1425,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STRXpre: { // str xt, [xn, #imm]! std::vector addresses; generateContiguousAddresses( - srcRegVals[1].get() + metadata.operands[1].mem.disp, 1, + operands[1].get() + metadata.operands[1].mem.disp, 1, dataSize_, addresses); setMemoryAddresses(addresses); break; @@ -1455,88 +1438,86 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STRWpost: // str wt, [xn], #imm case Opcode::AArch64_STRXpost: { // str xt, [xn], #imm std::vector addresses; - generateContiguousAddresses(srcRegVals[1].get(), 1, dataSize_, + generateContiguousAddresses(operands[1].get(), 1, dataSize_, addresses); setMemoryAddresses(addresses); break; } case Opcode::AArch64_STRHHpost: { // strh wt, [xn], #imm - setMemoryAddresses({{srcRegVals[1].get(), 2}}); + setMemoryAddresses({{operands[1].get(), 2}}); break; } case Opcode::AArch64_STRHHpre: { // strh wd, [xn, #imm]! setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_STRHHroW: { // strh wd, // [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 2}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 2}}); break; } case Opcode::AArch64_STRHHroX: { // strh wd, // [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 2}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 2}}); break; } case Opcode::AArch64_STRHHui: { // strh wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_STRQroX: { // str qt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 16}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 16}}); break; } case Opcode::AArch64_STRSroW: { // str st, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRSroX: { // str st, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRWroW: { // str wd, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRWroX: { // str wt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 4}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 4}}); break; } case Opcode::AArch64_STRXroW: { // str xd, [xn, wm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 8}}); break; } case Opcode::AArch64_STRXroX: { // str xt, [xn, xm{, extend {#amount}}] uint64_t offset = - extendOffset(srcRegVals[2].get(), metadata.operands[1]); - setMemoryAddresses({{srcRegVals[1].get() + offset, 8}}); + extendOffset(operands[2].get(), metadata.operands[1]); + setMemoryAddresses({{operands[1].get() + offset, 8}}); break; } case Opcode::AArch64_STR_PXI: { // str pt, [xn{, #imm, mul vl}] const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -1546,7 +1527,7 @@ span Instruction::generateAddresses() { case Opcode::AArch64_STR_ZXI: { // str zt, [xn{, #imm, mul vl}] const uint16_t partition_num = VL_bits / 8; - const uint64_t base = srcRegVals[1].get(); + const uint64_t base = operands[1].get(); const int64_t offset = static_cast(metadata.operands[1].mem.disp); @@ -1555,52 +1536,46 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_STURBBi: { // sturb wd, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 1}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 1}}); break; } case Opcode::AArch64_STURDi: { // stur dt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 8}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 8}}); break; } case Opcode::AArch64_STURHHi: { // sturh wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 2}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 2}}); break; } case Opcode::AArch64_STURQi: { // stur qt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, + {{operands[1].get() + metadata.operands[1].mem.disp, 16}}); break; } case Opcode::AArch64_STURSi: { // stur st, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 4}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 4}}); break; } case Opcode::AArch64_STURWi: { // stur wt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 4}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 4}}); break; } case Opcode::AArch64_STURXi: { // stur xt, [xn, #imm] setMemoryAddresses( - {{srcRegVals[1].get() + metadata.operands[1].mem.disp, - 8}}); + {{operands[1].get() + metadata.operands[1].mem.disp, 8}}); break; } case Opcode::AArch64_STXRW: { // stxr ws, wt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::AArch64_STXRX: { // stxr ws, xt, [xn] - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } default: diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 95eb704d03..0cf8b02c59 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -640,12 +640,12 @@ void Instruction::decode() { // Allocate enough entries in results vector results.resize(destinationRegisterCount + 1); // Allocate enough entries in the operands vector - srcRegVals.resize(sourceRegisterCount + 1); + operands.resize(sourceRegisterCount + 1); // Catch zero register references and pre-complete those operands for (uint16_t i = 0; i < sourceRegisterCount; i++) { if (sourceRegisters[i] == Instruction::ZERO_REGISTER) { - srcRegVals[i] = RegisterValue(0, 8); + operands[i] = RegisterValue(0, 8); numSrcOpsPending--; } } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index db7b25e452..03fe5a5410 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -88,17 +88,16 @@ void Instruction::execute() { break; } case MicroOpcode::OFFSET_IMM: { - results[0] = srcRegVals[0].get() + metadata.operands[2].imm; + results[0] = operands[0].get() + metadata.operands[2].imm; break; } case MicroOpcode::OFFSET_REG: { - results[0] = - srcRegVals[0].get() + srcRegVals[1].get(); + results[0] = operands[0].get() + operands[1].get(); break; } case MicroOpcode::STR_DATA: { setMemoryAddresses({{0, 0}}); - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } default: @@ -107,13 +106,12 @@ void Instruction::execute() { } else { switch (metadata.opcode) { case Opcode::AArch64_ADCXr: { // adc xd, xn, xm - auto [result, nzcv] = - arithmeticHelp::addCarry_3ops(srcRegVals); + auto [result, nzcv] = arithmeticHelp::addCarry_3ops(operands); results[0] = result; break; } case Opcode::AArch64_ADDPL_XXI: { // addpl xd, xn, #imm - auto x = srcRegVals[0].get(); + auto x = operands[0].get(); auto y = static_cast(metadata.operands[2].imm); // convert PL from VL_bits const uint64_t PL = VL_bits / 64; @@ -121,70 +119,70 @@ void Instruction::execute() { break; } case Opcode::AArch64_ADDPv16i8: { // addp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_ADDPv2i64: { // addp vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_ADDPv2i64p: { // addp dd, vn.2d - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_ADDPv4i32: { // addp vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_ADDPv8i16: { // addp vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_ADDSWri: { // adds wd, wn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(srcRegVals, metadata, true); + arithmeticHelp::addShift_imm(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSWrs: { // adds wd, wn, wm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_3ops(srcRegVals, metadata, true); + arithmeticHelp::addShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSWrx: { // adds wd, wn, wm{, extend {#amount}} - auto [result, nzcv] = arithmeticHelp::addExtend_3ops( - srcRegVals, metadata, true); + auto [result, nzcv] = + arithmeticHelp::addExtend_3ops(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_ADDSXri: { // adds xd, xn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(srcRegVals, metadata, true); + arithmeticHelp::addShift_imm(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_ADDSXrs: { // adds xd, xn, xm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_3ops(srcRegVals, metadata, true); + arithmeticHelp::addShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_ADDSXrx: // adds xd, xn, wm{, extend {#amount}} case Opcode::AArch64_ADDSXrx64: { // adds xd, xn, xm{, extend {#amount}} - auto [result, nzcv] = arithmeticHelp::addExtend_3ops( - srcRegVals, metadata, true); + auto [result, nzcv] = + arithmeticHelp::addExtend_3ops(operands, metadata, true); results[0] = nzcv; results[1] = RegisterValue(result, 8); break; } case Opcode::AArch64_ADDVL_XXI: { // addvl xd, xn, #imm - auto x = srcRegVals[0].get(); + auto x = operands[0].get(); auto y = static_cast(metadata.operands[2].imm); // convert VL from LEN (number of 128-bits) to bytes const uint64_t VL = VL_bits / 8; @@ -192,140 +190,135 @@ void Instruction::execute() { break; } case Opcode::AArch64_ADDVv4i16v: { // addv hd, vn.4h - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_ADDVv4i32v: { // addv sd, vn.4s - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_ADDVv8i8v: { // addv bd, vn.8b - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_ADDWri: { // add wd, wn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(srcRegVals, metadata, false); + arithmeticHelp::addShift_imm(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrs: { // add wd, wn, wm{, shift #amount} - auto [result, nzcv] = arithmeticHelp::addShift_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::addShift_3ops(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrx: { // add wd, wn, wm{, extend #amount} - auto [result, nzcv] = arithmeticHelp::addExtend_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::addExtend_3ops(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_ADDXri: { // add xd, xn, #imm{, shift} auto [result, nzcv] = - arithmeticHelp::addShift_imm(srcRegVals, metadata, false); + arithmeticHelp::addShift_imm(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADDXrs: { // add xd, xn, xm, {shift #amount} - auto [result, nzcv] = arithmeticHelp::addShift_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::addShift_3ops(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADDXrx: // add xd, xn, wm{, extend {#amount}} case Opcode::AArch64_ADDXrx64: { // add xd, xn, xm{, extend {#amount}} - auto [result, nzcv] = arithmeticHelp::addExtend_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::addExtend_3ops(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_ADD_ZI_B: { // add zdn.b, zdn.b, imm{, shift} - results[0] = - sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_D: { // add zdn.d, zdn.d, imm{, shift} - results[0] = - sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_H: { // add zdn.h zdn.h, imm{, shift} - results[0] = - sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZI_S: { // add zdn.s, zdn.s, imm{, shift} - results[0] = - sveHelp::sveAdd_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveAdd_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_B: { // add zdn.b, pg/m, zdn.b, zm.b - results[0] = - sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_D: { // add zdn.d, pg/m, zdn.d, zm.d results[0] = - sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_H: { // add zdn.h, pg/m, zdn.h, zm.h results[0] = - sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZPmZ_S: { // add zdn.s, pg/m, zdn.s, zm.s results[0] = - sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_B: { // add zd.b, zn.b, zm.b - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_D: { // add zd.d, zn.d, zm.d - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_H: { // add zd.h, zn.h, zm.h - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_ADD_ZZZ_S: { // add zd.s, zn.s, zm.s - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_ADDv16i8: { // add vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv1i64: { // add dd, dn, dm - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv2i32: { // add vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv2i64: { // add vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv4i16: { // add vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv4i32: { // add vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv8i16: { // add vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADDv8i8: { // add vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_ADR: { // adr xd, #imm @@ -343,21 +336,21 @@ void Instruction::execute() { case Opcode::AArch64_ADR_LSL_ZZZ_D_1: // adr zd.d, [zn.d, zm.d, lsl #1] case Opcode::AArch64_ADR_LSL_ZZZ_D_2: // adr zd.d, [zn.d, zm.d, lsl #2] case Opcode::AArch64_ADR_LSL_ZZZ_D_3: { // adr zd.d, [zn.d, zm.d, lsl #3] - results[0] = sveHelp::sveAdr_packedOffsets(srcRegVals, - metadata, VL_bits); + results[0] = sveHelp::sveAdr_packedOffsets(operands, metadata, + VL_bits); break; } case Opcode::AArch64_ADR_LSL_ZZZ_S_0: // adr zd.s, [zn.s, zm.s] case Opcode::AArch64_ADR_LSL_ZZZ_S_1: // adr zd.s, [zn.s, zm.s, lsl #1] case Opcode::AArch64_ADR_LSL_ZZZ_S_2: // adr zd.s, [zn.s, zm.s, lsl #2] case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { // adr zd.s, [zn.s, zm.s, lsl #3] - results[0] = sveHelp::sveAdr_packedOffsets(srcRegVals, - metadata, VL_bits); + results[0] = sveHelp::sveAdr_packedOffsets(operands, metadata, + VL_bits); break; } case Opcode::AArch64_ANDSWri: { // ands wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, true, + operands, metadata, true, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = nzcv; results[1] = {result, 8}; @@ -365,7 +358,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSWrs: { // ands wd, wn, wm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, true, + operands, metadata, true, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = nzcv; results[1] = {result, 8}; @@ -373,7 +366,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSXri: { // ands xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, true, + operands, metadata, true, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = nzcv; results[1] = result; @@ -381,7 +374,7 @@ void Instruction::execute() { } case Opcode::AArch64_ANDSXrs: { // ands xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, true, + operands, metadata, true, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = nzcv; results[1] = result; @@ -389,40 +382,40 @@ void Instruction::execute() { } case Opcode::AArch64_ANDWri: { // and wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ANDWrs: { // and wd, wn, wm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ANDXri: { // and xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = result; break; } case Opcode::AArch64_ANDXrs: { // and xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); results[0] = result; break; } case Opcode::AArch64_AND_PPzPP: { // and pd.b, pg/z, pn.b, pm.b results[0] = sveHelp::sveLogicOp_preds( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); break; } case Opcode::AArch64_AND_ZI: { // and zdn, zdn, #imm - const uint64_t* dn = srcRegVals[0].getAsVector(); + const uint64_t* dn = operands[0].getAsVector(); const uint64_t imm = static_cast(metadata.operands[2].imm); const uint16_t partition_num = VL_bits / 64; @@ -435,44 +428,44 @@ void Instruction::execute() { } case Opcode::AArch64_AND_ZPmZ_B: { // and zdn.b, pg/m, zdn.b, zm.b results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_D: { // and zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_H: { // and zdn.h, pg/m, zdn.h, zm.h results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint16_t x, uint16_t y) -> uint16_t { return x & y; }); break; } case Opcode::AArch64_AND_ZPmZ_S: { // and zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); break; } case Opcode::AArch64_ANDv16i8: { // and vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_ANDv8i8: { // and vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x & y; }); break; } case Opcode::AArch64_ASRVWr: { // asrv wd, wn, wm - results[0] = {logicalHelp::asrv_3gpr(srcRegVals), 8}; + results[0] = {logicalHelp::asrv_3gpr(operands), 8}; break; } case Opcode::AArch64_ASRVXr: { // asrv xd, xn, xm - results[0] = logicalHelp::asrv_3gpr(srcRegVals); + results[0] = logicalHelp::asrv_3gpr(operands); break; } case Opcode::AArch64_B: { // b label @@ -481,70 +474,68 @@ void Instruction::execute() { break; } case Opcode::AArch64_BFMWri: { // bfm wd, wn, #immr, #imms - results[0] = {bitmanipHelp::bfm_2imms(srcRegVals, metadata, - false, false), - 8}; + results[0] = { + bitmanipHelp::bfm_2imms(operands, metadata, false, false), + 8}; break; } case Opcode::AArch64_BFMXri: { // bfm xd, xn, #immr, #imms - results[0] = bitmanipHelp::bfm_2imms(srcRegVals, metadata, - false, false); + results[0] = + bitmanipHelp::bfm_2imms(operands, metadata, false, false); break; } case Opcode::AArch64_BICSWrs: { // bics wd, wn, wm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(srcRegVals, metadata, true); + logicalHelp::bicShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_BICSXrs: { // bics xd, xn, xm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(srcRegVals, metadata, true); + logicalHelp::bicShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_BICWrs: { // bic wd, wn, wm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(srcRegVals, metadata, false); + logicalHelp::bicShift_3ops(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_BICXrs: { // bic xd, xn, xm{, shift #amount} auto [result, nzcv] = - logicalHelp::bicShift_3ops(srcRegVals, metadata, false); + logicalHelp::bicShift_3ops(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_BICv16i8: { // bic vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBic_3ops(srcRegVals); + results[0] = neonHelp::vecBic_3ops(operands); break; } case Opcode::AArch64_BICv4i32: { // bic vd.4s, #imm{, lsl #shift} - results[0] = - neonHelp::vecBicShift_imm(srcRegVals, metadata); + results[0] = neonHelp::vecBicShift_imm(operands, metadata); break; } case Opcode::AArch64_BICv8i16: { // bic vd.8h, #imm{, lsl #shift} - results[0] = - neonHelp::vecBicShift_imm(srcRegVals, metadata); + results[0] = neonHelp::vecBicShift_imm(operands, metadata); break; } case Opcode::AArch64_BICv8i8: { // bic vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecBic_3ops(srcRegVals); + results[0] = neonHelp::vecBic_3ops(operands); break; } case Opcode::AArch64_BIFv16i8: { // bif vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBitwiseInsert<16>(srcRegVals, true); + results[0] = neonHelp::vecBitwiseInsert<16>(operands, true); break; } case Opcode::AArch64_BITv16i8: { // bit vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBitwiseInsert<16>(srcRegVals, false); + results[0] = neonHelp::vecBitwiseInsert<16>(operands, false); break; } case Opcode::AArch64_BITv8i8: { // bit vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecBitwiseInsert<8>(srcRegVals, false); + results[0] = neonHelp::vecBitwiseInsert<8>(operands, false); break; } case Opcode::AArch64_BL: { // bl #imm @@ -555,13 +546,13 @@ void Instruction::execute() { } case Opcode::AArch64_BLR: { // blr xn branchTaken_ = true; - branchAddress_ = srcRegVals[0].get(); + branchAddress_ = operands[0].get(); results[0] = static_cast(instructionAddress_ + 4); break; } case Opcode::AArch64_BR: { // br xn branchTaken_ = true; - branchAddress_ = srcRegVals[0].get(); + branchAddress_ = operands[0].get(); break; } case Opcode::AArch64_BRK: { @@ -569,12 +560,11 @@ void Instruction::execute() { break; } case Opcode::AArch64_BSLv16i8: { // bsl vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecBsl<16>(srcRegVals); + results[0] = neonHelp::vecBsl<16>(operands); break; } case Opcode::AArch64_Bcc: { // b.cond label - if (AuxFunc::conditionHolds(metadata.cc, - srcRegVals[0].get())) { + if (AuxFunc::conditionHolds(metadata.cc, operands[0].get())) { branchTaken_ = true; branchAddress_ = instructionAddress_ + metadata.operands[0].imm; } else { @@ -585,23 +575,23 @@ void Instruction::execute() { } case Opcode::AArch64_CASALW: { // casal ws, wt, [xn|sp] // LOAD / STORE - const uint32_t s = srcRegVals[0].get(); - const uint32_t t = srcRegVals[1].get(); + const uint32_t s = operands[0].get(); + const uint32_t t = operands[1].get(); const uint32_t n = memoryData[0].get(); if (n == s) memoryData[0] = t; break; } case Opcode::AArch64_CASALX: { // casal xs, xt, [xn|sp] // LOAD / STORE - const uint64_t s = srcRegVals[0].get(); - const uint64_t t = srcRegVals[1].get(); + const uint64_t s = operands[0].get(); + const uint64_t t = operands[1].get(); const uint64_t n = memoryData[0].get(); if (n == s) memoryData[0] = t; break; } case Opcode::AArch64_CBNZW: { // cbnz wn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - srcRegVals, metadata, instructionAddress_, + operands, metadata, instructionAddress_, [](uint32_t x) -> bool { return x != 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -609,7 +599,7 @@ void Instruction::execute() { } case Opcode::AArch64_CBNZX: { // cbnz xn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - srcRegVals, metadata, instructionAddress_, + operands, metadata, instructionAddress_, [](uint64_t x) -> bool { return x != 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -617,7 +607,7 @@ void Instruction::execute() { } case Opcode::AArch64_CBZW: { // cbz wn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - srcRegVals, metadata, instructionAddress_, + operands, metadata, instructionAddress_, [](uint32_t x) -> bool { return x == 0; }); branchTaken_ = taken; branchAddress_ = addr; @@ -625,85 +615,85 @@ void Instruction::execute() { } case Opcode::AArch64_CBZX: { // cbz xn, #imm auto [taken, addr] = conditionalHelp::condBranch_cmpToZero( - srcRegVals, metadata, instructionAddress_, + operands, metadata, instructionAddress_, [](uint64_t x) -> bool { return x == 0; }); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_CCMNWi: { // ccmn wn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmn_imm(srcRegVals, metadata); + results[0] = conditionalHelp::ccmn_imm(operands, metadata); break; } case Opcode::AArch64_CCMNXi: { // ccmn xn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmn_imm(srcRegVals, metadata); + results[0] = conditionalHelp::ccmn_imm(operands, metadata); break; } case Opcode::AArch64_CCMPWi: { // ccmp wn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmp_imm(srcRegVals, metadata); + results[0] = conditionalHelp::ccmp_imm(operands, metadata); break; } case Opcode::AArch64_CCMPWr: { // ccmp wn, wm, #nzcv, cc - results[0] = conditionalHelp::ccmp_reg(srcRegVals, metadata); + results[0] = conditionalHelp::ccmp_reg(operands, metadata); break; } case Opcode::AArch64_CCMPXi: { // ccmp xn, #imm, #nzcv, cc - results[0] = conditionalHelp::ccmp_imm(srcRegVals, metadata); + results[0] = conditionalHelp::ccmp_imm(operands, metadata); break; } case Opcode::AArch64_CCMPXr: { // ccmp xn, xm, #nzcv, cc - results[0] = conditionalHelp::ccmp_reg(srcRegVals, metadata); + results[0] = conditionalHelp::ccmp_reg(operands, metadata); break; } case Opcode::AArch64_CLZXr: { // clz xd, xn - results[0] = arithmeticHelp::clz_reg(srcRegVals); + results[0] = arithmeticHelp::clz_reg(operands); break; } case Opcode::AArch64_CMEQv16i8: { // cmeq vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecCompare( - srcRegVals, false, + operands, false, [](uint8_t x, uint8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv16i8rz: { // cmeq vd.16b, vn.16b, #0 results[0] = neonHelp::vecCompare( - srcRegVals, true, + operands, true, [](uint8_t x, uint8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv4i32: { // cmeq vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecCompare( - srcRegVals, false, + operands, false, [](uint32_t x, uint32_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv8i8: { // cmeq vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecCompare( - srcRegVals, false, + operands, false, [](int8_t x, int8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMEQv8i8rz: { // cmeq vd.8b, vn.8b, #0 results[0] = neonHelp::vecCompare( - srcRegVals, true, + operands, true, [](int8_t x, int8_t y) -> bool { return (x == y); }); break; } case Opcode::AArch64_CMHIv4i32: { // cmhi vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecCompare( - srcRegVals, false, + operands, false, [](uint32_t x, uint32_t y) -> bool { return (x > y); }); break; } case Opcode::AArch64_CMHSv16i8: { // cmhs vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecCompare( - srcRegVals, false, + operands, false, [](int8_t x, int8_t y) -> bool { return (x >= y); }); break; } case Opcode::AArch64_CMPEQ_PPzZI_B: { // cmpeq pd.b, pg/z, zn.b, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](uint8_t x, uint8_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -711,7 +701,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_D: { // cmpeq pd.d, pg/z, zn.d, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](uint64_t x, uint64_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -719,7 +709,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_H: { // cmpeq pd.h, pg/z, zn.h, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](uint16_t x, uint16_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -727,7 +717,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZI_S: { // cmpeq pd.s, pg/z, zn.s, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](uint32_t x, uint32_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -735,7 +725,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_B: { // cmpeq pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint8_t x, uint8_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -743,7 +733,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_D: { // cmpeq pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint64_t x, uint64_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -751,7 +741,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_H: { // cmpeq pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint16_t x, uint16_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -759,7 +749,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPEQ_PPzZZ_S: { // cmpeq pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint32_t x, uint32_t y) -> bool { return x == y; }); results[0] = nzcv; results[1] = output; @@ -767,7 +757,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_B: { // cmpgt pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int8_t x, int8_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -775,7 +765,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_D: { // cmpgt pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int64_t x, int64_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -783,7 +773,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_H: { // cmpgt pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int16_t x, int16_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -791,7 +781,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPGT_PPzZZ_S: { // cmpgt pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int32_t x, int32_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -799,7 +789,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_B: { // cmphi pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint8_t x, uint8_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -807,7 +797,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_D: { // cmphi pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint64_t x, uint64_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -815,7 +805,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_H: { // cmphi pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint16_t x, uint16_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -823,7 +813,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPHI_PPzZZ_S: { // cmphi pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](uint32_t x, uint32_t y) -> bool { return x > y; }); results[0] = nzcv; results[1] = output; @@ -831,7 +821,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_B: { // cmpne pd.b, pg/z. zn.b, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](int8_t x, int8_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -839,7 +829,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_D: { // cmpne pd.d, pg/z. zn.d, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](int64_t x, int64_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -847,7 +837,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_H: { // cmpne pd.h, pg/z. zn.h, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](int16_t x, int16_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -855,7 +845,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZI_S: { // cmpne pd.s, pg/z. zn.s, #imm auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](int32_t x, int32_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -863,7 +853,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_B: { // cmpne pd.b, pg/z, zn.b, zm.b auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int8_t x, int8_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -871,7 +861,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_D: { // cmpne pd.d, pg/z, zn.d, zm.d auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int64_t x, int64_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -879,7 +869,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_H: { // cmpne pd.h, pg/z, zn.h, zm.h auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int16_t x, int16_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -887,7 +877,7 @@ void Instruction::execute() { } case Opcode::AArch64_CMPNE_PPzZZ_S: { // cmpne pd.s, pg/z, zn.s, zm.s auto [output, nzcv] = sveHelp::sveCmpPredicated_toPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](int32_t x, int32_t y) -> bool { return x != y; }); results[0] = nzcv; results[1] = output; @@ -906,19 +896,19 @@ void Instruction::execute() { break; } case Opcode::AArch64_CNTP_XPP_B: { // cntp xd, pg, pn.b - results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); + results[0] = sveHelp::sveCntp(operands, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_D: { // cntp xd, pg, pn.d - results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); + results[0] = sveHelp::sveCntp(operands, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_H: { // cntp xd, pg, pn.h - results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); + results[0] = sveHelp::sveCntp(operands, VL_bits); break; } case Opcode::AArch64_CNTP_XPP_S: { // cntp xd, pg, pn.s - results[0] = sveHelp::sveCntp(srcRegVals, VL_bits); + results[0] = sveHelp::sveCntp(operands, VL_bits); break; } case Opcode::AArch64_CNTW_XPiI: { // cntw xd{, pattern{, #imm}} @@ -926,94 +916,91 @@ void Instruction::execute() { break; } case Opcode::AArch64_CNTv8i8: { // cnt vd.8b, vn.8b - results[0] = neonHelp::vecCountPerByte(srcRegVals); + results[0] = neonHelp::vecCountPerByte(operands); break; } case Opcode::AArch64_CPY_ZPzI_B: { // cpy zd.b, pg/z, #imm{, shift} - results[0] = sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_D: { // cpy zd.d, pg/z, #imm{, shift} - results[0] = - sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_H: { // cpy zd.h, pg/z, #imm{, shift} - results[0] = - sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_CPY_ZPzI_S: { // cpy zd.s, pg/z, #imm{, shift} - results[0] = - sveHelp::sveCpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveCpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_DUPi32: { // dup vd, vn.s[index] - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, false); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, false); break; } case Opcode::AArch64_DUPi64: { // dup vd, vn.d[index] - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, false); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, false); break; } case Opcode::AArch64_CSELWr: { // csel wd, wn, wm, cc results[0] = { conditionalHelp::cs_4ops( - srcRegVals, metadata, [](uint32_t x) -> uint32_t { return x; }), + operands, metadata, [](uint32_t x) -> uint32_t { return x; }), 8}; break; } case Opcode::AArch64_CSELXr: { // csel xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - srcRegVals, metadata, [](uint64_t x) -> uint64_t { return x; }); + operands, metadata, [](uint64_t x) -> uint64_t { return x; }); break; } case Opcode::AArch64_CSINCWr: { // csinc wd, wn, wm, cc results[0] = {conditionalHelp::cs_4ops( - srcRegVals, metadata, + operands, metadata, [](uint32_t x) -> uint32_t { return x + 1; }), 8}; break; } case Opcode::AArch64_CSINCXr: { // csinc xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - srcRegVals, metadata, [](uint64_t x) -> uint64_t { return x + 1; }); + operands, metadata, [](uint64_t x) -> uint64_t { return x + 1; }); break; } case Opcode::AArch64_CSINVWr: { // csinv wd, wn, wm, cc - results[0] = {conditionalHelp::cs_4ops( - srcRegVals, metadata, - [](uint32_t x) -> uint32_t { return ~x; }), - 8}; + results[0] = { + conditionalHelp::cs_4ops( + operands, metadata, [](uint32_t x) -> uint32_t { return ~x; }), + 8}; break; } case Opcode::AArch64_CSINVXr: { // csinv xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - srcRegVals, metadata, [](uint64_t x) -> uint64_t { return ~x; }); + operands, metadata, [](uint64_t x) -> uint64_t { return ~x; }); break; } case Opcode::AArch64_CSNEGWr: { // csneg wd, wn, wm, cc results[0] = { conditionalHelp::cs_4ops( - srcRegVals, metadata, [](int32_t x) -> int32_t { return -x; }), + operands, metadata, [](int32_t x) -> int32_t { return -x; }), 8}; break; } case Opcode::AArch64_CSNEGXr: { // csneg xd, xn, xm, cc results[0] = conditionalHelp::cs_4ops( - srcRegVals, metadata, [](uint64_t x) -> uint64_t { return -x; }); + operands, metadata, [](uint64_t x) -> uint64_t { return -x; }); break; } case Opcode::AArch64_DECB_XPiI: { // decb xdn{, pattern{, MUL #imm}} results[0] = - sveHelp::sveDec_scalar(srcRegVals, metadata, VL_bits); + sveHelp::sveDec_scalar(operands, metadata, VL_bits); break; } case Opcode::AArch64_DECD_XPiI: { // decd xdn{, pattern{, MUL #imm}} results[0] = - sveHelp::sveDec_scalar(srcRegVals, metadata, VL_bits); + sveHelp::sveDec_scalar(operands, metadata, VL_bits); break; } case Opcode::AArch64_DMB: { // dmb option|#imm @@ -1030,48 +1017,48 @@ void Instruction::execute() { break; } case Opcode::AArch64_DUP_ZI_B: { // dup zd.b, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_D: { // dup zd.d, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_H: { // dup zd.h, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZI_S: { // dup zd.s, #imm{, shift} - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_DUP_ZR_B: { // dup zd.b, wn - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_D: { // dup zd.d, xn - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_H: { // dup zd.h, wn - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZR_S: { // dup zd.s, wn - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_DUP_ZZI_D: { // dup zd.d, zn.d[#imm] results[0] = - sveHelp::sveDup_vecIndexed(srcRegVals, metadata, VL_bits); + sveHelp::sveDup_vecIndexed(operands, metadata, VL_bits); break; } case Opcode::AArch64_DUP_ZZI_Q: { // dup zd.q, zn.q[#imm] @@ -1079,7 +1066,7 @@ void Instruction::execute() { // can use uint64_t. const uint16_t index = 2 * static_cast(metadata.operands[1].vector_index); - const uint64_t* n = srcRegVals[0].getAsVector(); + const uint64_t* n = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 128; uint64_t out[32] = {0}; @@ -1097,126 +1084,126 @@ void Instruction::execute() { } case Opcode::AArch64_DUP_ZZI_S: { // dup zd.s, zn.s[#imm] results[0] = - sveHelp::sveDup_vecIndexed(srcRegVals, metadata, VL_bits); + sveHelp::sveDup_vecIndexed(operands, metadata, VL_bits); break; } case Opcode::AArch64_DUPv16i8gpr: { // dup vd.16b, wn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_DUPv2i32gpr: { // dup vd.2s, wn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_DUPv2i32lane: { // dup vd.2s, vn.s[index] - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, false); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, false); break; } case Opcode::AArch64_DUPv2i64gpr: { // dup vd.2d, xn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_DUPv2i64lane: { // dup vd.2d, vn.d[index] - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, false); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, false); break; } case Opcode::AArch64_DUPv4i16gpr: { // dup vd.4h, wn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_DUPv4i32gpr: { // dup vd.4s, wn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_DUPv4i32lane: { // dup vd.4s, vn.s[index] - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, false); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, false); break; } case Opcode::AArch64_DUPv8i16gpr: { // dup vd.8h, wn - results[0] = neonHelp::vecDup_gprOrIndex(srcRegVals, - metadata, true); + results[0] = + neonHelp::vecDup_gprOrIndex(operands, metadata, true); break; } case Opcode::AArch64_EORWri: { // eor wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_EORWrs: { // eor wd, wn, wm{, shift #imm} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_EORXri: { // eor xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); results[0] = result; break; } case Opcode::AArch64_EORXrs: { // eor xd, xn, xm{, shift #amount} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); results[0] = result; break; } case Opcode::AArch64_EOR_PPzPP: { results[0] = sveHelp::sveLogicOp_preds( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_B: { // eor zdn.b, pg/m, zdn.b, zm.b results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_D: { // eor zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_H: { // eor zdn.h, pg/m, zdn.h, zm.h results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint16_t x, uint16_t y) -> uint16_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZPmZ_S: { // eor zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); break; } case Opcode::AArch64_EOR_ZZZ: { // eor zd.d, zn.d, zm.d results[0] = sveHelp::sveLogicOpUnPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); break; } case Opcode::AArch64_EORv16i8: { // eor vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EORv8i8: { // eor vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x ^ y; }); break; } case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { // MOVA zd.b, pg/m, zanh.b[ws, @@ -1227,13 +1214,13 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 8; - const uint8_t* zd = srcRegVals[0].getAsVector(); - const uint64_t* pg = srcRegVals[1].getAsVector(); + const uint8_t* zd = operands[0].getAsVector(); + const uint64_t* pg = operands[1].getAsVector(); const uint64_t sliceNum = - (srcRegVals[2 + rowCount].get() + + (operands[2 + rowCount].get() + static_cast(metadata.operands[2].sme_index.disp)) % rowCount; - const uint8_t* zanRow = srcRegVals[2 + sliceNum].getAsVector(); + const uint8_t* zanRow = operands[2 + sliceNum].getAsVector(); uint8_t out[256] = {0}; for (int elem = 0; elem < rowCount; elem++) { @@ -1249,651 +1236,638 @@ void Instruction::execute() { } case Opcode::AArch64_EXTRWrri: { // extr wd, wn, wm, #lsb results[0] = { - bitmanipHelp::extrLSB_registers(srcRegVals, metadata), 8}; + bitmanipHelp::extrLSB_registers(operands, metadata), 8}; break; } case Opcode::AArch64_EXTRXrri: { // extr xd, xn, xm, #lsb results[0] = - bitmanipHelp::extrLSB_registers(srcRegVals, metadata); + bitmanipHelp::extrLSB_registers(operands, metadata); break; } case Opcode::AArch64_EXTv16i8: { // ext vd.16b, vn.16b, vm.16b, #index results[0] = - neonHelp::vecExtVecs_index(srcRegVals, metadata); + neonHelp::vecExtVecs_index(operands, metadata); break; } case Opcode::AArch64_EXTv8i8: { // ext vd.8b, vn.8b, vm.8b, #index - results[0] = - neonHelp::vecExtVecs_index(srcRegVals, metadata); + results[0] = neonHelp::vecExtVecs_index(operands, metadata); break; } case Opcode::AArch64_FABDv2f64: { // fabd vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFabd(srcRegVals); + results[0] = neonHelp::vecFabd(operands); break; } case Opcode::AArch64_FABDv4f32: { // fabd vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFabd(srcRegVals); + results[0] = neonHelp::vecFabd(operands); break; } case Opcode::AArch64_FABD32: { // fabd sd, sn, sm - results[0] = floatHelp::fabd_3ops(srcRegVals); + results[0] = floatHelp::fabd_3ops(operands); break; } case Opcode::AArch64_FABD64: { // fabd dd, dn, dm - results[0] = floatHelp::fabd_3ops(srcRegVals); + results[0] = floatHelp::fabd_3ops(operands); break; } case Opcode::AArch64_FABSDr: { // fabs dd, dn - results[0] = floatHelp::fabs_2ops(srcRegVals); + results[0] = floatHelp::fabs_2ops(operands); break; } case Opcode::AArch64_FABSSr: { // fabs sd, sn - results[0] = floatHelp::fabs_2ops(srcRegVals); + results[0] = floatHelp::fabs_2ops(operands); break; } case Opcode::AArch64_FABS_ZPmZ_D: { // fabs zd.d, pg/m, zn.d - results[0] = sveHelp::sveFabsPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFabsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FABS_ZPmZ_S: { // fabs zd.s, pg/m, zn.s - results[0] = sveHelp::sveFabsPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFabsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FABSv2f64: { // fabs vd.2d, vn.2d - results[0] = neonHelp::vecFabs_2ops(srcRegVals); + results[0] = neonHelp::vecFabs_2ops(operands); break; } case Opcode::AArch64_FABSv4f32: { // fabs vd.4s, vn.4s - results[0] = neonHelp::vecFabs_2ops(srcRegVals); + results[0] = neonHelp::vecFabs_2ops(operands); break; } case Opcode::AArch64_FADDA_VPZ_D: { // fadda dd, pg/m, dn, zm.d - results[0] = sveHelp::sveFaddaPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFaddaPredicated(operands, VL_bits); break; } case Opcode::AArch64_FADDA_VPZ_S: { // fadda sd, pg/m, sn, zm.s - results[0] = sveHelp::sveFaddaPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFaddaPredicated(operands, VL_bits); break; } case Opcode::AArch64_FADDDrr: { // fadd dd, dn, dm - results[0] = {arithmeticHelp::add_3ops(srcRegVals), 256}; + results[0] = {arithmeticHelp::add_3ops(operands), 256}; break; } case Opcode::AArch64_FADDPv2f32: { // faddp vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_FADDPv2f64: { // faddp vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_FADDPv2i32p: { // faddp dd, vn.2s - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_FADDPv2i64p: { // faddp dd, vn.2d - results[0] = neonHelp::vecSumElems_2ops(srcRegVals); + results[0] = neonHelp::vecSumElems_2ops(operands); break; } case Opcode::AArch64_FADDPv4f32: { // faddp vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAddp_3ops(srcRegVals); + results[0] = neonHelp::vecAddp_3ops(operands); break; } case Opcode::AArch64_FADDSrr: { // fadd sd, sn, sm - results[0] = {arithmeticHelp::add_3ops(srcRegVals), 256}; + results[0] = {arithmeticHelp::add_3ops(operands), 256}; break; } case Opcode::AArch64_FADD_ZPmI_D: { // fadd zdn.d, pg/m, zdn.d, const - results[0] = sveHelp::sveAddPredicated_const(srcRegVals, - metadata, VL_bits); + results[0] = sveHelp::sveAddPredicated_const(operands, metadata, + VL_bits); break; } case Opcode::AArch64_FADD_ZPmI_S: { // fadd zdn.s, pg/m, zdn.s, const - results[0] = sveHelp::sveAddPredicated_const(srcRegVals, - metadata, VL_bits); + results[0] = + sveHelp::sveAddPredicated_const(operands, metadata, VL_bits); break; } case Opcode::AArch64_FADD_ZPmZ_D: { // fadd zdn.d, pg/m, zdn.d, zm.d - results[0] = - sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FADD_ZPmZ_S: { // fadd zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveAddPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FADD_ZZZ_D: { // fadd zd.d, zn.d, zm.d - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_FADD_ZZZ_S: { // fadd zd.s, zn.s, zm.s - results[0] = sveHelp::sveAdd_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveAdd_3ops(operands, VL_bits); break; } case Opcode::AArch64_FADDv2f32: { // fadd vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_FADDv2f64: { // fadd vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_FADDv4f32: { // fadd vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecAdd_3ops(srcRegVals); + results[0] = neonHelp::vecAdd_3ops(operands); break; } case Opcode::AArch64_FCADD_ZPmZ_D: { // fcadd zdn.d, pg/m, zdn.d, zm.d, // #imm results[0] = - sveHelp::sveFcaddPredicated(srcRegVals, metadata, VL_bits); + sveHelp::sveFcaddPredicated(operands, metadata, VL_bits); break; } case Opcode::AArch64_FCCMPDrr: // fccmp sn, sm, #nzcv, cc case Opcode::AArch64_FCCMPEDrr: { // fccmpe sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(srcRegVals, metadata); + results[0] = floatHelp::fccmp(operands, metadata); break; } case Opcode::AArch64_FCCMPESrr: { // fccmpe sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(srcRegVals, metadata); + results[0] = floatHelp::fccmp(operands, metadata); break; } case Opcode::AArch64_FCCMPSrr: { // fccmp sn, sm, #nzcv, cc - results[0] = floatHelp::fccmp(srcRegVals, metadata); + results[0] = floatHelp::fccmp(operands, metadata); break; } case Opcode::AArch64_FCMEQv2i32rz: { // fcmeq vd.2s, vd.2s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x == y; }); + operands, true, [](float x, float y) -> bool { return x == y; }); break; } case Opcode::AArch64_FCMEQv4i32rz: { // fcmeq vd.4s vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x == y; }); + operands, true, [](float x, float y) -> bool { return x == y; }); break; } case Opcode::AArch64_FCMGE_PPzZ0_D: { // fcmge pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZ0_S: { // fcmge pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZZ_D: { // fcmge pd.d, pg/z, zn.d, zm.d results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGE_PPzZZ_S: { // fcmge pd.s, pg/z, zn.s, zm.s results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2f32: { // fcmge vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecFCompare( - srcRegVals, false, [](float x, float y) -> bool { return x >= y; }); + operands, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2f64: { // fcmge vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecFCompare( - srcRegVals, false, - [](float x, double y) -> bool { return x >= y; }); + operands, false, [](float x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv2i64rz: { // fcmge vd.2d, vn.2d, 0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, - [](double x, double y) -> bool { return x >= y; }); + operands, true, [](double x, double y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv4f32: { // fcmge vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecFCompare( - srcRegVals, false, [](float x, float y) -> bool { return x >= y; }); + operands, false, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGEv4i32rz: { // fcmge vd.4s, vn.4s, 0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x >= y; }); + operands, true, [](float x, float y) -> bool { return x >= y; }); break; } case Opcode::AArch64_FCMGT_PPzZ0_D: { // fcmgt pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZ0_S: { // fcmgt pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZZ_D: { // fcmgt pd.d, pg/z, zn.d, zm.d results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGT_PPzZZ_S: { // fcmgt pd.s, pg/z, zn.s, zm. results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, false, + operands, metadata, VL_bits, false, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2i32rz: { // fcmgt vd.2s, vn.2s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x > y; }); + operands, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2i64rz: { // fcmgt vd.2d, vn.2d, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](double x, double y) -> bool { return x > y; }); + operands, true, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv2f64: { // fcmgt vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecFCompare( - srcRegVals, false, - [](double x, double y) -> bool { return x > y; }); + operands, false, [](double x, double y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv4f32: { // fcmgt vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecFCompare( - srcRegVals, false, [](float x, float y) -> bool { return x > y; }); + operands, false, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMGTv4i32rz: { // fcmgt vd.4s, vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x > y; }); + operands, true, [](float x, float y) -> bool { return x > y; }); break; } case Opcode::AArch64_FCMLA_ZPmZZ_D: { // fcmla zda, pg/m, zn, zm, #imm results[0] = - sveHelp::sveFcmlaPredicated(srcRegVals, metadata, VL_bits); + sveHelp::sveFcmlaPredicated(operands, metadata, VL_bits); break; } case Opcode::AArch64_FCMLE_PPzZ0_D: { // fcmle pd.d, pg/z, zn.d, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](double x, double y) -> bool { return x <= y; }); break; } case Opcode::AArch64_FCMLE_PPzZ0_S: { // fcmle pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](float x, float y) -> bool { return x <= y; }); break; } case Opcode::AArch64_FCMLT_PPzZ0_S: { // fcmlt pd.s, pg/z, zn.s, #0.0 results[0] = sveHelp::sveComparePredicated_vecsToPred( - srcRegVals, metadata, VL_bits, true, + operands, metadata, VL_bits, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv2i32rz: { // fcmlt vd.2s, vn.2s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x < y; }); + operands, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv2i64rz: { // fcmlt vd.2d, vn.2d, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](double x, double y) -> bool { return x < y; }); + operands, true, [](double x, double y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMLTv4i32rz: { // fcmlt vd.4s, vn.4s, #0.0 results[0] = neonHelp::vecFCompare( - srcRegVals, true, [](float x, float y) -> bool { return x < y; }); + operands, true, [](float x, float y) -> bool { return x < y; }); break; } case Opcode::AArch64_FCMPDri: { // fcmp dn, #imm - results[0] = floatHelp::fcmp(srcRegVals, true); + results[0] = floatHelp::fcmp(operands, true); break; } case Opcode::AArch64_FCMPDrr: { // fcmp dn, dm - results[0] = floatHelp::fcmp(srcRegVals, false); + results[0] = floatHelp::fcmp(operands, false); break; } case Opcode::AArch64_FCMPEDri: { // fcmpe dn, #imm - results[0] = floatHelp::fcmp(srcRegVals, true); + results[0] = floatHelp::fcmp(operands, true); break; } case Opcode::AArch64_FCMPEDrr: { // fcmpe dn, dm - results[0] = floatHelp::fcmp(srcRegVals, false); + results[0] = floatHelp::fcmp(operands, false); break; } case Opcode::AArch64_FCMPESri: { // fcmpe sn, #imm - results[0] = floatHelp::fcmp(srcRegVals, true); + results[0] = floatHelp::fcmp(operands, true); break; } case Opcode::AArch64_FCMPESrr: { // fcmpe sn, sm - results[0] = floatHelp::fcmp(srcRegVals, false); + results[0] = floatHelp::fcmp(operands, false); break; } case Opcode::AArch64_FCMPSri: { // fcmp sn, #imm - results[0] = floatHelp::fcmp(srcRegVals, true); + results[0] = floatHelp::fcmp(operands, true); break; } case Opcode::AArch64_FCMPSrr: { // fcmp sn, sm - results[0] = floatHelp::fcmp(srcRegVals, false); + results[0] = floatHelp::fcmp(operands, false); break; } case Opcode::AArch64_FCPY_ZPmI_D: { // fcpy zd.d, pg/m, #const - results[0] = - sveHelp::sveFcpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveFcpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_FCPY_ZPmI_S: { // fcpy zd.s, pg/m, #const - results[0] = sveHelp::sveFcpy_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveFcpy_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_FCSELDrrr: { // fcsel dd, dn, dm, cond results[0] = { conditionalHelp::cs_4ops( - srcRegVals, metadata, [](double x) -> double { return x; }), + operands, metadata, [](double x) -> double { return x; }), 256}; break; } case Opcode::AArch64_FCSELSrrr: { // fcsel sd, sn, sm, cond results[0] = { - conditionalHelp::cs_4ops(srcRegVals, metadata, + conditionalHelp::cs_4ops(operands, metadata, [](float x) -> float { return x; }), 256}; break; } case Opcode::AArch64_FCVTASUWDr: { // fcvtas wd, dn - results[0] = {static_cast(round(srcRegVals[0].get())), + results[0] = {static_cast(round(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTASUXDr: { // fcvtas xd, dn - results[0] = static_cast(round(srcRegVals[0].get())); + results[0] = static_cast(round(operands[0].get())); break; } case Opcode::AArch64_FCVTDSr: { // fcvt dd, sn // TODO: Handle NaNs, denorms, and saturation? - results[0] = neonHelp::vecFcvtl(srcRegVals, false); + results[0] = neonHelp::vecFcvtl(operands, false); break; } case Opcode::AArch64_FCVTLv2i32: { // fcvtl vd.2d, vn.2s - results[0] = neonHelp::vecFcvtl(srcRegVals, false); + results[0] = neonHelp::vecFcvtl(operands, false); break; } case Opcode::AArch64_FCVTLv4i32: { // fcvtl2 vd.2d, vn.4s - results[0] = neonHelp::vecFcvtl(srcRegVals, true); + results[0] = neonHelp::vecFcvtl(operands, true); break; } case Opcode::AArch64_FCVTNv2i32: { // fcvtn vd.2s, vn.2d - results[0] = neonHelp::vecFcvtn(srcRegVals, false); + results[0] = neonHelp::vecFcvtn(operands, false); break; } case Opcode::AArch64_FCVTNv4i32: { // fcvtn2 vd.4s, vn.2d - results[0] = neonHelp::vecFcvtn(srcRegVals, true); + results[0] = neonHelp::vecFcvtn(operands, true); break; } case Opcode::AArch64_FCVTSDr: { // fcvt sd, dn // TODO: Handle NaNs, denorms, and saturation? - results[0] = neonHelp::vecFcvtl(srcRegVals, false); + results[0] = neonHelp::vecFcvtl(operands, false); break; } case Opcode::AArch64_FCVTZSUWDr: { // fcvtzs wd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), 8}; + static_cast(std::trunc(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTZSUWSr: { // fcvtzs wd, sn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), 8}; + static_cast(std::trunc(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTZSUXDr: { // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), 8}; + static_cast(std::trunc(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: { // fcvtzs zd.d, pg/m, zn.d results[0] = - sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtzsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: { // fcvtzs zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtzsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_StoD: { // fcvtzs zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtzsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FCVTZS_ZPmZ_StoS: { // fcvtzs zd.s, pg/m, zn.s results[0] = - sveHelp::sveFcvtzsPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtzsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FCVTZSv2f64: { // fcvtzs vd.2d, vn.2d - results[0] = neonHelp::vecFcvtzs(srcRegVals); + results[0] = neonHelp::vecFcvtzs(operands); break; } case Opcode::AArch64_FCVTZUUWDr: { // fcvtzu wd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), 8}; + static_cast(std::trunc(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTZUUWSr: { // fcvtzu wd, sn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), 8}; + static_cast(std::trunc(operands[0].get())), 8}; break; } case Opcode::AArch64_FCVTZUUXDr: { // fcvtzu xd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = - static_cast(std::trunc(srcRegVals[0].get())); + static_cast(std::trunc(operands[0].get())); break; } case Opcode::AArch64_FCVTZUUXSr: { // fcvtzu xd, sn // TODO: Handle NaNs, denorms, and saturation - results[0] = - static_cast(std::trunc(srcRegVals[0].get())); + results[0] = static_cast(std::trunc(operands[0].get())); break; } case Opcode::AArch64_FCVTZUv1i64: { // fcvtzu dd, dn // TODO: Handle NaNs, denorms, and saturation results[0] = { - static_cast(std::trunc(srcRegVals[0].get())), - 256}; + static_cast(std::trunc(operands[0].get())), 256}; break; } case Opcode::AArch64_FCVT_ZPmZ_DtoS: { // fcvt zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_FCVT_ZPmZ_StoD: { // fcvt zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_FDIVDrr: { // fdiv dd, dn, dm - results[0] = {divideHelp::div_3ops(srcRegVals), 256}; + results[0] = {divideHelp::div_3ops(operands), 256}; break; } case Opcode::AArch64_FDIVR_ZPmZ_D: { // fdivr zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](double x, double y) -> double { return (y / x); }); break; } case Opcode::AArch64_FDIVR_ZPmZ_S: { // fdivr zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](float x, float y) -> float { return (y / x); }); break; } case Opcode::AArch64_FDIVSrr: { // fdiv sd, sn, sm - results[0] = {divideHelp::div_3ops(srcRegVals), 256}; + results[0] = {divideHelp::div_3ops(operands), 256}; break; } case Opcode::AArch64_FDIV_ZPmZ_D: { // fdiv zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](double x, double y) -> double { return (x / y); }); break; } case Opcode::AArch64_FDIVv2f64: { // fdiv vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return x / y; }); + operands, [](double x, double y) -> double { return x / y; }); break; } case Opcode::AArch64_FDUP_ZI_D: { // fdup zd.d, #imm - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_FDUP_ZI_S: { // fdup zd.s, #imm - results[0] = sveHelp::sveDup_immOrScalar(srcRegVals, metadata, + results[0] = sveHelp::sveDup_immOrScalar(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_FMADDDrrr: { // fmadd dn, dm, da - results[0] = {multiplyHelp::madd_4ops(srcRegVals), 256}; + results[0] = {multiplyHelp::madd_4ops(operands), 256}; break; } case Opcode::AArch64_FMADDSrrr: { // fmadd sn, sm, sa - results[0] = {multiplyHelp::madd_4ops(srcRegVals), 256}; + results[0] = {multiplyHelp::madd_4ops(operands), 256}; break; } case Opcode::AArch64_FMAD_ZPmZZ_D: { // fmad zd.d, pg/m, zn.d, zm.d - results[0] = - sveHelp::sveFmadPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmadPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMAD_ZPmZZ_S: { // fmad zd.s, pg/m, zn.s, zm.s - results[0] = - sveHelp::sveFmadPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmadPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMAXNMDrr: { // fmaxnm dd, dn, dm - results[0] = floatHelp::fmaxnm_3ops(srcRegVals); + results[0] = floatHelp::fmaxnm_3ops(operands); break; } case Opcode::AArch64_FMAXNMPv2i64p: { // fmaxnmp dd, vd.2d - results[0] = neonHelp::vecMaxnmp_2ops(srcRegVals); + results[0] = neonHelp::vecMaxnmp_2ops(operands); break; } case Opcode::AArch64_FMAXNMSrr: { // fmaxnm sd, sn, sm - results[0] = floatHelp::fmaxnm_3ops(srcRegVals); + results[0] = floatHelp::fmaxnm_3ops(operands); break; } case Opcode::AArch64_FMAXNMv2f64: { // fmaxnm vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, + operands, [](double x, double y) -> double { return std::fmax(x, y); }); break; } case Opcode::AArch64_FMINNMDrr: { // fminnm dd, dn, dm - results[0] = floatHelp::fminnm_3ops(srcRegVals); + results[0] = floatHelp::fminnm_3ops(operands); break; } case Opcode::AArch64_FMINNMPv2i64p: { // fminnmp dd, vd.2d - results[0] = neonHelp::vecMinv_2ops(srcRegVals); + results[0] = neonHelp::vecMinv_2ops(operands); break; } case Opcode::AArch64_FMINNMSrr: { // fminnm sd, sn, sm - results[0] = floatHelp::fminnm_3ops(srcRegVals); + results[0] = floatHelp::fminnm_3ops(operands); break; } case Opcode::AArch64_FMINNMv2f64: { // fminnm vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, + operands, [](double x, double y) -> double { return std::fmin(x, y); }); break; } case Opcode::AArch64_FMLA_ZPmZZ_D: { // fmla zd.d, pg/m, zn.d, zm.d - results[0] = - sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMLA_ZPmZZ_S: { // fmla zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMLAv2f32: { // fmla vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecFmla_3vecs(srcRegVals); + results[0] = neonHelp::vecFmla_3vecs(operands); break; } case Opcode::AArch64_FMLA_ZZZI_D: { // fmla zda.d, zn.d, zm.d[index] results[0] = - sveHelp::sveMlaIndexed_vecs(srcRegVals, metadata, VL_bits); + sveHelp::sveMlaIndexed_vecs(operands, metadata, VL_bits); break; } case Opcode::AArch64_FMLA_ZZZI_S: { // fmla zda.s, zn.s, zm.s[index] results[0] = - sveHelp::sveMlaIndexed_vecs(srcRegVals, metadata, VL_bits); + sveHelp::sveMlaIndexed_vecs(operands, metadata, VL_bits); break; } case Opcode::AArch64_FMLAv2f64: { // fmla vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFmla_3vecs(srcRegVals); + results[0] = neonHelp::vecFmla_3vecs(operands); break; } case Opcode::AArch64_FMLAv2i32_indexed: { // fmla vd.2s, vn.2s, // vm.2s[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); + neonHelp::vecFmlaIndexed_3vecs(operands, metadata); break; } case Opcode::AArch64_FMLAv2i64_indexed: { // fmla vd.2d, vn.2d, // vm.d[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); + neonHelp::vecFmlaIndexed_3vecs(operands, metadata); break; } case Opcode::AArch64_FMLAv4f32: { // fmla vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFmla_3vecs(srcRegVals); + results[0] = neonHelp::vecFmla_3vecs(operands); break; } case Opcode::AArch64_FMLAv4i32_indexed: { // fmla vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmlaIndexed_3vecs(srcRegVals, metadata); + neonHelp::vecFmlaIndexed_3vecs(operands, metadata); break; } case Opcode::AArch64_FMLS_ZPmZZ_D: { // fmls zd.d, pg/m, zn.d, zm.d - results[0] = - sveHelp::sveFmlsPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmlsPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMLS_ZPmZZ_S: { // fmls zd.s, pg/m, zn.s, zm.s - results[0] = - sveHelp::sveFmlsPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmlsPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMLSv2f64: { // fmls vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFmls_3vecs(srcRegVals); + results[0] = neonHelp::vecFmls_3vecs(operands); break; } case Opcode::AArch64_FMLSv2i64_indexed: { results[0] = - neonHelp::vecFmlsIndexed_3vecs(srcRegVals, metadata); + neonHelp::vecFmlsIndexed_3vecs(operands, metadata); break; } case Opcode::AArch64_FMLSv4f32: { // fmls vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFmls_3vecs(srcRegVals); + results[0] = neonHelp::vecFmls_3vecs(operands); break; } case Opcode::AArch64_FMLSv4i32_indexed: { // fmls vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmlsIndexed_3vecs(srcRegVals, metadata); + neonHelp::vecFmlsIndexed_3vecs(operands, metadata); break; } case Opcode::AArch64_FMOPA_MPPZZ_D: { // fmopa zada.d, pn/m, pm/m, zn.d, @@ -1904,16 +1878,16 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 64; - const uint64_t* pn = srcRegVals[rowCount].getAsVector(); - const uint64_t* pm = srcRegVals[rowCount + 1].getAsVector(); - const double* zn = srcRegVals[rowCount + 2].getAsVector(); - const double* zm = srcRegVals[rowCount + 3].getAsVector(); + const uint64_t* pn = operands[rowCount].getAsVector(); + const uint64_t* pm = operands[rowCount + 1].getAsVector(); + const double* zn = operands[rowCount + 2].getAsVector(); + const double* zm = operands[rowCount + 3].getAsVector(); // zn is row, zm is col for (int row = 0; row < rowCount; row++) { double outRow[32] = {0}; uint64_t shifted_active_row = 1ull << ((row % 8) * 8); - const double* zadaRow = srcRegVals[row].getAsVector(); + const double* zadaRow = operands[row].getAsVector(); for (int col = 0; col < rowCount; col++) { double zadaElem = zadaRow[col]; uint64_t shifted_active_col = 1ull << ((col % 8) * 8); @@ -1935,16 +1909,16 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t rowCount = VL_bits / 32; - const uint64_t* pn = srcRegVals[rowCount].getAsVector(); - const uint64_t* pm = srcRegVals[rowCount + 1].getAsVector(); - const float* zn = srcRegVals[rowCount + 2].getAsVector(); - const float* zm = srcRegVals[rowCount + 3].getAsVector(); + const uint64_t* pn = operands[rowCount].getAsVector(); + const uint64_t* pm = operands[rowCount + 1].getAsVector(); + const float* zn = operands[rowCount + 2].getAsVector(); + const float* zm = operands[rowCount + 3].getAsVector(); // zn is row, zm is col for (int row = 0; row < rowCount; row++) { float outRow[64] = {0}; uint64_t shifted_active_row = 1ull << ((row % 16) * 4); - const float* zadaRow = srcRegVals[row].getAsVector(); + const float* zadaRow = operands[row].getAsVector(); for (int col = 0; col < rowCount; col++) { float zadaElem = zadaRow[col]; uint64_t shifted_active_col = 1ull << ((col % 16) * 4); @@ -1959,11 +1933,11 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVDXHighr: { // fmov xd, vn.d[1] - results[0] = srcRegVals[0].getAsVector()[1]; + results[0] = operands[0].getAsVector()[1]; break; } case Opcode::AArch64_FMOVDXr: { // fmov xd, dn - results[0] = srcRegVals[0].get(); + results[0] = operands[0].get(); break; } case Opcode::AArch64_FMOVDi: { // fmov dn, #imm @@ -1971,11 +1945,11 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVDr: { // fmov dd, dn - results[0] = {srcRegVals[0].get(), 256}; + results[0] = {operands[0].get(), 256}; break; } case Opcode::AArch64_FMOVSWr: { // fmov wd, sn - results[0] = {srcRegVals[0].get(), 8}; + results[0] = {operands[0].get(), 8}; break; } case Opcode::AArch64_FMOVSi: { // fmov sn, #imm @@ -1983,21 +1957,20 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMOVSr: { // fmov sd, sn - results[0] = {srcRegVals[0].get(), 256}; + results[0] = {operands[0].get(), 256}; break; } case Opcode::AArch64_FMOVWSr: { // fmov sd, wn - results[0] = {srcRegVals[0].get(), 256}; + results[0] = {operands[0].get(), 256}; break; } case Opcode::AArch64_FMOVXDHighr: { // fmov vd.d[1], xn - double out[2] = {srcRegVals[0].get(), - srcRegVals[1].get()}; + double out[2] = {operands[0].get(), operands[1].get()}; results[0] = {out, 256}; break; } case Opcode::AArch64_FMOVXDr: { // fmov dd, xn - results[0] = {srcRegVals[0].get(), 256}; + results[0] = {operands[0].get(), 256}; break; } case Opcode::AArch64_FMOVv2f32_ns: { // fmov vd.2s, #imm @@ -2013,325 +1986,321 @@ void Instruction::execute() { break; } case Opcode::AArch64_FMSB_ZPmZZ_D: { // fmsb zd.d, pg/m, zn.d, zm.d - results[0] = - sveHelp::sveFmsbPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmsbPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMSB_ZPmZZ_S: { // fmsb zd.s, pg/m, zn.s, zm.s - results[0] = - sveHelp::sveFmsbPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmsbPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_FMSUBDrrr: { // fmsub dn, dm, da - results[0] = {multiplyHelp::msub_4ops(srcRegVals), 256}; + results[0] = {multiplyHelp::msub_4ops(operands), 256}; break; } case Opcode::AArch64_FMSUBSrrr: { // fmsub sn, sm, sa - results[0] = {multiplyHelp::msub_4ops(srcRegVals), 256}; + results[0] = {multiplyHelp::msub_4ops(operands), 256}; break; } case Opcode::AArch64_FMULDrr: { // fmul dd, dn, dm - results[0] = {multiplyHelp::mul_3ops(srcRegVals), 256}; + results[0] = {multiplyHelp::mul_3ops(operands), 256}; break; } case Opcode::AArch64_FMULSrr: { // fmul sd, sn, sm - results[0] = {multiplyHelp::mul_3ops(srcRegVals), 256}; + results[0] = {multiplyHelp::mul_3ops(operands), 256}; break; } case Opcode::AArch64_FMUL_ZPmI_D: { // fmul zd.d, pg/m, zn.d, #imm - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_FMUL_ZPmI_S: { // fmul zd.s, pg/m, zn.s, #imm - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, - VL_bits, true); + results[0] = + sveHelp::sveMulPredicated(operands, metadata, VL_bits, true); break; } case Opcode::AArch64_FMUL_ZPmZ_D: { // fmul zdn.d, pg/m, zdn.d, zm.d - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_FMUL_ZPmZ_S: { // fmul zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_FMUL_ZZZ_D: { // fmul zd.d, zn.d, zm.d - results[0] = sveHelp::sveFmul_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmul_3ops(operands, VL_bits); break; } case Opcode::AArch64_FMUL_ZZZ_S: { // fmul zd.s, zn.s, zm.s - results[0] = sveHelp::sveFmul_3ops(srcRegVals, VL_bits); + results[0] = sveHelp::sveFmul_3ops(operands, VL_bits); break; } case Opcode::AArch64_FMULv1i32_indexed: { // fmul sd, sn, vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); + neonHelp::vecFmulIndexed_vecs(operands, metadata); break; } case Opcode::AArch64_FMULv1i64_indexed: { // fmul dd, dn, vm.d[index] results[0] = - neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); + neonHelp::vecFmulIndexed_vecs(operands, metadata); break; } case Opcode::AArch64_FMULv2f32: { // fmul vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](float x, float y) -> float { return x * y; }); + operands, [](float x, float y) -> float { return x * y; }); break; } case Opcode::AArch64_FMULv2f64: { // fmul vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return x * y; }); + operands, [](double x, double y) -> double { return x * y; }); break; } case Opcode::AArch64_FMULv2i32_indexed: { // fmul vd.2s, vn.2s, // vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); + neonHelp::vecFmulIndexed_vecs(operands, metadata); break; } case Opcode::AArch64_FMULv2i64_indexed: { // fmul vd.2d, vn.2d, // vm.d[index] results[0] = - neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); + neonHelp::vecFmulIndexed_vecs(operands, metadata); break; } case Opcode::AArch64_FMULv4f32: { // fmul vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](float x, float y) -> float { return x * y; }); + operands, [](float x, float y) -> float { return x * y; }); break; } case Opcode::AArch64_FMULv4i32_indexed: { // fmul vd.4s, vn.4s, // vm.s[index] results[0] = - neonHelp::vecFmulIndexed_vecs(srcRegVals, metadata); + neonHelp::vecFmulIndexed_vecs(operands, metadata); break; } case Opcode::AArch64_FNEGDr: { // fneg dd, dn - results[0] = {-srcRegVals[0].get(), 256}; + results[0] = {-operands[0].get(), 256}; break; } case Opcode::AArch64_FNEGSr: { // fneg sd, sn - results[0] = {-srcRegVals[0].get(), 256}; + results[0] = {-operands[0].get(), 256}; break; } case Opcode::AArch64_FNEG_ZPmZ_D: { // fneg zd.d, pg/m, zn.d - results[0] = sveHelp::sveFnegPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnegPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNEG_ZPmZ_S: { // fneg zd.s, pg/m, zn.s - results[0] = sveHelp::sveFnegPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnegPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNEGv2f64: { // fneg vd.2d, vn.2d - results[0] = neonHelp::vecFneg_2ops(srcRegVals); + results[0] = neonHelp::vecFneg_2ops(operands); break; } case Opcode::AArch64_FNEGv4f32: { // fneg vd.4s, vn.4s - results[0] = neonHelp::vecFneg_2ops(srcRegVals); + results[0] = neonHelp::vecFneg_2ops(operands); break; } case Opcode::AArch64_FNMADDDrrr: { // fnmadd dd, dn, dm, da - results[0] = floatHelp::fnmadd_4ops(srcRegVals); + results[0] = floatHelp::fnmadd_4ops(operands); break; } case Opcode::AArch64_FNMADDSrrr: { // fnmadd sd, sn, sm, sa - results[0] = floatHelp::fnmadd_4ops(srcRegVals); + results[0] = floatHelp::fnmadd_4ops(operands); break; } case Opcode::AArch64_FNMLS_ZPmZZ_D: { // fnmls zd.d, pg/m, zn.d, zm.d - results[0] = sveHelp::sveFnmlsPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnmlsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNMLS_ZPmZZ_S: { // fnmls zd.s, pg/m, zn.s, zm.s - results[0] = sveHelp::sveFnmlsPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnmlsPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNMSB_ZPmZZ_D: { // fnmsb zdn.d, pg/m, zm.d, za.d - results[0] = sveHelp::sveFnmsbPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnmsbPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNMSB_ZPmZZ_S: { // fnmsb zdn.s, pg/m, zm.s, za.s - results[0] = sveHelp::sveFnmsbPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveFnmsbPredicated(operands, VL_bits); break; } case Opcode::AArch64_FNMSUBDrrr: { // fnmsub dd, dn, dm, da - results[0] = floatHelp::fnmsub_4ops(srcRegVals); + results[0] = floatHelp::fnmsub_4ops(operands); break; } case Opcode::AArch64_FNMSUBSrrr: { // fnmsub sd, sn, sm, sa - results[0] = floatHelp::fnmsub_4ops(srcRegVals); + results[0] = floatHelp::fnmsub_4ops(operands); break; } case Opcode::AArch64_FNMULDrr: { // fnmul dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return -(x * y); }); + operands, [](double x, double y) -> double { return -(x * y); }); break; } case Opcode::AArch64_FNMULSrr: { // fnmul sd, sn, sm results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](float x, float y) -> float { return -(x * y); }); + operands, [](float x, float y) -> float { return -(x * y); }); break; } case Opcode::AArch64_FRINTADr: { // frinta dd, dn - results[0] = {round(srcRegVals[0].get()), 256}; + results[0] = {round(operands[0].get()), 256}; break; } case Opcode::AArch64_FRINTN_ZPmZ_D: { // frintn zd.d, pg/m, zn.d results[0] = - sveHelp::sveFrintnPredicated(srcRegVals, VL_bits); + sveHelp::sveFrintnPredicated(operands, VL_bits); break; } case Opcode::AArch64_FRINTN_ZPmZ_S: { // frintn zd.s, pg/m, zn.s results[0] = - sveHelp::sveFrintnPredicated(srcRegVals, VL_bits); + sveHelp::sveFrintnPredicated(operands, VL_bits); break; } case Opcode::AArch64_FRINTPDr: { // frintp dd, dn - results[0] = floatHelp::frintpScalar_2ops(srcRegVals); + results[0] = floatHelp::frintpScalar_2ops(operands); break; } case Opcode::AArch64_FRINTPSr: { // frintp sd, sn - results[0] = floatHelp::frintpScalar_2ops(srcRegVals); + results[0] = floatHelp::frintpScalar_2ops(operands); break; } case Opcode::AArch64_FRSQRTEv1i32: { // frsqrte sd, sn - results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); + results[0] = neonHelp::vecFrsqrte_2ops(operands); break; } case Opcode::AArch64_FRSQRTEv1i64: { // frsqrte dd, dn - results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); + results[0] = neonHelp::vecFrsqrte_2ops(operands); break; } case Opcode::AArch64_FRSQRTEv2f32: { // frsqrte vd.2s, vn.2s - results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); + results[0] = neonHelp::vecFrsqrte_2ops(operands); break; } case Opcode::AArch64_FRSQRTEv2f64: { // frsqrte vd.2d, vn.2d - results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); + results[0] = neonHelp::vecFrsqrte_2ops(operands); break; } case Opcode::AArch64_FRSQRTEv4f32: { // frsqrte vd.4s, vn.4s - results[0] = neonHelp::vecFrsqrte_2ops(srcRegVals); + results[0] = neonHelp::vecFrsqrte_2ops(operands); break; } case Opcode::AArch64_FRSQRTS32: { // frsqrts sd, sn, sm - results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); + results[0] = neonHelp::vecFrsqrts_3ops(operands); break; } case Opcode::AArch64_FRSQRTS64: { // frsqrts dd, dn, dm - results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); + results[0] = neonHelp::vecFrsqrts_3ops(operands); break; } case Opcode::AArch64_FRSQRTSv2f32: { // frsqrts vd.2s, vn.2s, vn.2s - results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); + results[0] = neonHelp::vecFrsqrts_3ops(operands); break; } case Opcode::AArch64_FRSQRTSv2f64: { // frsqrts vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); + results[0] = neonHelp::vecFrsqrts_3ops(operands); break; } case Opcode::AArch64_FRSQRTSv4f32: { // frsqrts vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecFrsqrts_3ops(srcRegVals); + results[0] = neonHelp::vecFrsqrts_3ops(operands); break; } case Opcode::AArch64_FSQRTDr: { // fsqrt dd, dn - results[0] = {::sqrt(srcRegVals[0].get()), 256}; + results[0] = {::sqrt(operands[0].get()), 256}; break; } case Opcode::AArch64_FSQRTSr: { // fsqrt sd, sn - results[0] = {::sqrtf(srcRegVals[0].get()), 256}; + results[0] = {::sqrtf(operands[0].get()), 256}; break; } case Opcode::AArch64_FSQRT_ZPmZ_D: { // fsqrt zd.d, pg/m, zn.d results[0] = - sveHelp::sveFsqrtPredicated_2vecs(srcRegVals, VL_bits); + sveHelp::sveFsqrtPredicated_2vecs(operands, VL_bits); break; } case Opcode::AArch64_FSQRT_ZPmZ_S: { // fsqrt zd.s, pg/m, zn.s results[0] = - sveHelp::sveFsqrtPredicated_2vecs(srcRegVals, VL_bits); + sveHelp::sveFsqrtPredicated_2vecs(operands, VL_bits); break; } case Opcode::AArch64_FSQRTv2f64: { // fsqrt vd.2d, vn.2d - results[0] = neonHelp::vecFsqrt_2ops(srcRegVals); + results[0] = neonHelp::vecFsqrt_2ops(operands); break; } case Opcode::AArch64_FSQRTv4f32: { // fsqrt vd.4s, vn.4s - results[0] = neonHelp::vecFsqrt_2ops(srcRegVals); + results[0] = neonHelp::vecFsqrt_2ops(operands); break; } case Opcode::AArch64_FSUBDrr: { // fsub dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return x - y; }); + operands, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUBR_ZPmZ_D: { // fsubr zdn.d, pg/m, zdn.d, zm.d results[0] = - sveHelp::sveSubrPredicated_3vecs(srcRegVals, VL_bits); + sveHelp::sveSubrPredicated_3vecs(operands, VL_bits); break; } case Opcode::AArch64_FSUBR_ZPmZ_S: { // fsubr zdn.s, pg/m, zdn.s, zm.s - results[0] = - sveHelp::sveSubrPredicated_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSubrPredicated_3vecs(operands, VL_bits); break; } case Opcode::AArch64_FSUBSrr: { // fsub ss, sn, sm results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return x - y; }); + operands, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUB_ZPmI_D: { // fsub zdn.d, pg/m, zdn.d, #imm - results[0] = sveHelp::sveSubPredicated_imm(srcRegVals, metadata, - VL_bits); + results[0] = + sveHelp::sveSubPredicated_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_FSUB_ZPmI_S: { // fsub zdn.s, pg/m, zdn.s, #imm results[0] = - sveHelp::sveSubPredicated_imm(srcRegVals, metadata, VL_bits); + sveHelp::sveSubPredicated_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_FSUB_ZPmZ_D: { // fsub zdn.d, pg/m, zdn.d, zm.d results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUB_ZPmZ_S: { // fsub zdn.s, pg/m, zdn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, - [](float x, float y) -> float { return x - y; }); + operands, VL_bits, [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_FSUB_ZZZ_D: { // fsub zd.d, zn.d, zm.d - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_FSUB_ZZZ_S: { // fsub zd.s, zn.s, zm.s - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_FSUBv2f32: { results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](float x, float y) -> float { return x - y; }); + operands, [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_FSUBv2f64: { // fsub vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](double x, double y) -> double { return x - y; }); + operands, [](double x, double y) -> double { return x - y; }); break; } case Opcode::AArch64_FSUBv4f32: { // fsub vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](float x, float y) -> float { return x - y; }); + operands, [](float x, float y) -> float { return x - y; }); break; } case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, // #imm}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; @@ -2352,7 +2321,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, // zm.d, LSL #3] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -2372,7 +2341,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, [zn.d{, // #imm}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; int64_t out[32] = {0}; @@ -2390,7 +2359,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, // [, zm.d, lsl #2] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; @@ -2408,7 +2377,7 @@ void Instruction::execute() { case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, // [, zm.s, sxtw] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; @@ -2429,161 +2398,158 @@ void Instruction::execute() { } case Opcode::AArch64_INCB_XPiI: { // incb xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); + sveHelp::sveInc_gprImm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCD_XPiI: { // incd xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); + sveHelp::sveInc_gprImm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCD_ZPiI: { // incd zdn.d{, pattern{, #imm}} - results[0] = - sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCH_XPiI: { // inch xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); + sveHelp::sveInc_gprImm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCH_ZPiI: { // inch zdn.h{, pattern{, #imm}} - results[0] = - sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCP_XP_B: { // incp xdn, pm.b - results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); + results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); break; } case Opcode::AArch64_INCP_XP_D: { // incp xdn, pm.d - results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); + results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); break; } case Opcode::AArch64_INCP_XP_H: { // incp xdn, pm.h - results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); + results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); break; } case Opcode::AArch64_INCP_XP_S: { // incp xdn, pm.s - results[0] = sveHelp::sveIncp_gpr(srcRegVals, VL_bits); + results[0] = sveHelp::sveIncp_gpr(operands, VL_bits); break; } case Opcode::AArch64_INCW_XPiI: { // incw xdn{, pattern{, #imm}} results[0] = - sveHelp::sveInc_gprImm(srcRegVals, metadata, VL_bits); + sveHelp::sveInc_gprImm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INCW_ZPiI: { // incw zdn.s{, pattern{, #imm}} - results[0] = - sveHelp::sveInc_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveInc_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_INDEX_II_B: { // index zd.b, #imm, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, - true, true); + results[0] = + sveHelp::sveIndex(operands, metadata, VL_bits, true, true); break; } case Opcode::AArch64_INDEX_II_D: { // index zd.d, #imm, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, - true, true); + results[0] = + sveHelp::sveIndex(operands, metadata, VL_bits, true, true); break; } case Opcode::AArch64_INDEX_II_H: { // index zd.h, #imm, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, - true, true); + results[0] = + sveHelp::sveIndex(operands, metadata, VL_bits, true, true); break; } case Opcode::AArch64_INDEX_II_S: { // index zd.s, #imm, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, VL_bits, - true, true); + results[0] = + sveHelp::sveIndex(operands, metadata, VL_bits, true, true); break; } case Opcode::AArch64_INDEX_IR_B: { // index zd.b, #imm, wn - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_D: { // index zd.d, #imm, xn - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_H: { // index zd.h, #imm, wn - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_IR_S: { // index zd.s, #imm, wn - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, true, false); break; } case Opcode::AArch64_INDEX_RI_B: { // index zd.b, wn, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_D: { // index zd.d, xn, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_H: { // index zd.h, wn, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RI_S: { // index zd.s, wn, #imm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, true); break; } case Opcode::AArch64_INDEX_RR_B: { // index zd.b, wn, wm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_D: { // index zd.d, xn, xm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_H: { // index zd.h, wn, wm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INDEX_RR_S: { // index zd.s, wn, wm - results[0] = sveHelp::sveIndex(srcRegVals, metadata, + results[0] = sveHelp::sveIndex(operands, metadata, VL_bits, false, false); break; } case Opcode::AArch64_INSvi16gpr: { // ins vd.h[index], wn - results[0] = neonHelp::vecInsIndex_gpr( - srcRegVals, metadata); + results[0] = neonHelp::vecInsIndex_gpr(operands, + metadata); break; } case Opcode::AArch64_INSvi32gpr: { // ins vd.s[index], wn - results[0] = neonHelp::vecInsIndex_gpr( - srcRegVals, metadata); + results[0] = neonHelp::vecInsIndex_gpr(operands, + metadata); break; } case Opcode::AArch64_INSvi32lane: { // ins vd.s[index1], vn.s[index2] - results[0] = neonHelp::vecIns_2Index(srcRegVals, metadata); + results[0] = neonHelp::vecIns_2Index(operands, metadata); break; } case Opcode::AArch64_INSvi64gpr: { // ins vd.d[index], xn - results[0] = neonHelp::vecInsIndex_gpr( - srcRegVals, metadata); + results[0] = neonHelp::vecInsIndex_gpr(operands, + metadata); break; } case Opcode::AArch64_INSvi64lane: { // ins vd.d[index1], vn.d[index2] - results[0] = neonHelp::vecIns_2Index(srcRegVals, metadata); + results[0] = neonHelp::vecIns_2Index(operands, metadata); break; } case Opcode::AArch64_INSvi8gpr: { // ins vd.b[index], wn - results[0] = neonHelp::vecInsIndex_gpr( - srcRegVals, metadata); + results[0] = neonHelp::vecInsIndex_gpr(operands, + metadata); break; } case Opcode::AArch64_LD1_MXIPXX_H_D: { // ld1d {zath.d[ws, #imm]}, pg/z, @@ -2593,9 +2559,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2618,7 +2584,7 @@ void Instruction::execute() { results[i] = {out, 256}; else // Maintain un-updated rows. - results[i] = srcRegVals[i]; + results[i] = operands[i]; } break; } @@ -2629,9 +2595,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2639,7 +2605,7 @@ void Instruction::execute() { for (int i = 0; i < partition_num; i++) { uint64_t* row = - const_cast(srcRegVals[i].getAsVector()); + const_cast(operands[i].getAsVector()); uint64_t shifted_active = 1ull << ((i % 8) * 8); if (pg[i / 8] & shifted_active) { row[sliceNum] = data[i]; @@ -2657,9 +2623,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2682,7 +2648,7 @@ void Instruction::execute() { results[i] = {out, 256}; else // Maintain un-updated rows. - results[i] = srcRegVals[i]; + results[i] = operands[i]; } break; } @@ -2693,9 +2659,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -2703,7 +2669,7 @@ void Instruction::execute() { for (int i = 0; i < partition_num; i++) { uint32_t* row = - const_cast(srcRegVals[i].getAsVector()); + const_cast(operands[i].getAsVector()); uint64_t shifted_active = 1ull << ((i % 16) * 4); if (pg[i / 16] & shifted_active) { row[sliceNum] = data[i]; @@ -2716,7 +2682,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1B: { // ld1b {zt.b}, pg/z, [xn, xm] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 8; const uint8_t* data = memoryData[0].getAsVector(); @@ -2736,7 +2702,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 8; const uint8_t* data = memoryData[0].getAsVector(); @@ -2754,7 +2720,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1D: { // ld1d {zt.d}, pg/z, [xn, xm, lsl #3] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; const uint64_t* data = memoryData[0].getAsVector(); @@ -2774,7 +2740,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1D_IMM_REAL: { // ld1d {zt.d}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; const uint64_t* data = memoryData[0].getAsVector(); @@ -2793,7 +2759,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1H: { // ld1h {zt.h}, pg/z, [xn, xm, lsl #1] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 16; const uint16_t* data = memoryData[0].getAsVector(); @@ -2819,9 +2785,9 @@ void Instruction::execute() { // if #imm post-index, value can only be 16 const uint64_t postIndex = (metadata.operands[2].type == ARM64_OP_REG) - ? srcRegVals[1].get() + ? operands[1].get() : 16; - results[1] = srcRegVals[0].get() + postIndex; + results[1] = operands[0].get() + postIndex; break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] @@ -2831,7 +2797,7 @@ void Instruction::execute() { uint16_t index = 0; // Check if any lanes are active, otherwise set all to 0 and break early bool active = false; - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { active = true; @@ -2853,7 +2819,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_D_IMM: { // ld1rqd {zd.d}, pg/z, [xn{, #imm}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint64_t out[32] = {0}; const uint64_t* data = memoryData[0].getAsVector(); @@ -2877,7 +2843,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_W: { // ld1rqw {zd.s}, pg/z, [xn, xm, lsl #2] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; const uint32_t* data = memoryData[0].getAsVector(); @@ -2903,7 +2869,7 @@ void Instruction::execute() { } case Opcode::AArch64_LD1RQ_W_IMM: { // ld1rqw {zd.s}, pg/z, [xn{, #imm}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint32_t out[64] = {0}; const uint32_t* data = memoryData[0].getAsVector(); @@ -2934,7 +2900,7 @@ void Instruction::execute() { // Check if any lanes are active, otherwise set all to 0 and break early bool active = false; - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); for (int i = 0; i < 4; i++) { if (p[i] != 0) { active = true; @@ -2965,7 +2931,7 @@ void Instruction::execute() { uint8_t out[16] = {val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv1d: { // ld1r {vt.1d}, [xn] @@ -2980,7 +2946,7 @@ void Instruction::execute() { uint64_t val = memoryData[0].get(); uint64_t out[2] = {val, 0}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv2d: { // ld1r {vt.2d}, [xn] @@ -2995,7 +2961,7 @@ void Instruction::execute() { uint64_t val = memoryData[0].get(); uint64_t out[2] = {val, val}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv2s: { // ld1r {vt.2s}, [xn] @@ -3010,7 +2976,7 @@ void Instruction::execute() { uint32_t val = memoryData[0].get(); uint32_t out[4] = {val, val, 0, 0}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv4h: { // ld1r {vt.4h}, [xn] @@ -3025,7 +2991,7 @@ void Instruction::execute() { uint16_t val = memoryData[0].get(); uint16_t out[8] = {val, val, val, val, 0, 0, 0, 0}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv4s: { // ld1r {vt.4s}, [xn] @@ -3040,7 +3006,7 @@ void Instruction::execute() { uint32_t val = memoryData[0].get(); uint32_t out[4] = {val, val, val, val}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv8b: { // ld1r {vt.8b}, [xn] @@ -3057,7 +3023,7 @@ void Instruction::execute() { uint8_t out[16] = {val, val, val, val, val, val, val, val, 0, 0, 0, 0, 0, 0, 0, 0}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Rv8h: { // ld1r {vt.8h}, [xn] @@ -3072,7 +3038,7 @@ void Instruction::execute() { uint16_t val = memoryData[0].get(); uint16_t out[8] = {val, val, val, val, val, val, val, val}; results[0] = {out, 256}; - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD1Fourv16b: // ld1 {vt1.16b, vt2.16b, vt3.16b, @@ -3105,9 +3071,9 @@ void Instruction::execute() { results[3] = memoryData[3].zeroExtend(memoryData[3].size(), 256); // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? srcRegVals[1].get() + ? operands[1].get() : 64; - results[4] = srcRegVals[0].get() + postIndex; + results[4] = operands[0].get() + postIndex; break; } case Opcode::AArch64_LD1Twov16b: // ld1 {vt1.16b, vt2.16b}, [xn] @@ -3134,14 +3100,14 @@ void Instruction::execute() { // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? srcRegVals[1].get() + ? operands[1].get() : 32; - results[2] = srcRegVals[0].get() + postIndex; + results[2] = operands[0].get() + postIndex; break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; const uint32_t* data = memoryData[0].getAsVector(); @@ -3161,7 +3127,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1W_IMM_REAL: { // ld1w {zt.s}, pg/z, [xn{, #imm, // mul vl}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; const uint32_t* data = memoryData[0].getAsVector(); @@ -3181,7 +3147,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1i32: { // ld1 {vt.s}[index], [xn] // LOAD const int index = metadata.operands[0].vector_index; - const uint32_t* vt = srcRegVals[0].getAsVector(); + const uint32_t* vt = operands[0].getAsVector(); uint32_t out[4]; for (int i = 0; i < 4; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; @@ -3192,7 +3158,7 @@ void Instruction::execute() { case Opcode::AArch64_LD1i64: { // ld1 {vt.d}[index], [xn] // LOAD const int index = metadata.operands[0].vector_index; - const uint64_t* vt = srcRegVals[0].getAsVector(); + const uint64_t* vt = operands[0].getAsVector(); uint64_t out[2]; for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; @@ -3203,13 +3169,13 @@ void Instruction::execute() { case Opcode::AArch64_LD1i64_POST: { // ld1 {vt.d}[index], [xn], #8 // LOAD const int index = metadata.operands[0].vector_index; - const uint64_t* vt = srcRegVals[0].getAsVector(); + const uint64_t* vt = operands[0].getAsVector(); uint64_t out[2]; for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData[0].get() : vt[i]; } results[0] = {out, 256}; - results[1] = srcRegVals[1].get() + metadata.operands[2].imm; + results[1] = operands[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LD2D: // ld2d {zt1.d, zt2.d}, pg/z, [, xm, @@ -3217,7 +3183,7 @@ void Instruction::execute() { case Opcode::AArch64_LD2D_IMM: { // ld2d {zt1.d, zt2.d}, pg/z, [{, // #imm, mul vl}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3261,15 +3227,15 @@ void Instruction::execute() { results[1] = {t2, 256}; uint64_t offset = 32; if (metadata.operandCount == 4) { - offset = srcRegVals[3].get(); + offset = operands[3].get(); } - results[2] = srcRegVals[2].get() + offset; + results[2] = operands[2].get() + offset; break; } case Opcode::AArch64_LD3D_IMM: { // ld3d {zt1.d, zt2.d, zt3.d}, pg/z, // [xn|sp{, #imm, MUL VL}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3295,7 +3261,7 @@ void Instruction::execute() { case Opcode::AArch64_LD4D_IMM: { // ld4d {zt1.d, zt2.d, zt3.d, zt4.d}, // pg/z, [xn|sp{, #imm, MUL VL}] // LOAD - const uint64_t* p = srcRegVals[0].getAsVector(); + const uint64_t* p = operands[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; std::vector data = { memoryData[0].getAsVector(), @@ -3326,7 +3292,7 @@ void Instruction::execute() { // LOAD results[0] = memoryData[0].zeroExtend(4, 8); memoryData[0] = RegisterValue( - memoryData[0].get() + srcRegVals[0].get(), 4); + memoryData[0].get() + operands[0].get(), 4); break; } case Opcode::AArch64_LDARB: { // ldarb wt, [xn] @@ -3380,7 +3346,7 @@ void Instruction::execute() { (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = memoryData[1].zeroExtend(dataSize_, regSize); - results[2] = srcRegVals[0].get() + metadata.operands[3].imm; + results[2] = operands[0].get() + metadata.operands[3].imm; break; } case Opcode::AArch64_LDPDpre: // ldp dt1, dt2, [xn, #imm]! @@ -3393,7 +3359,7 @@ void Instruction::execute() { results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = memoryData[1].zeroExtend(dataSize_, regSize); results[2] = - srcRegVals[0].get() + metadata.operands[2].mem.disp; + operands[0].get() + metadata.operands[2].mem.disp; break; } case Opcode::AArch64_LDPSWi: { // ldpsw xt1, xt2, [xn {, #imm}] @@ -3405,14 +3371,14 @@ void Instruction::execute() { case Opcode::AArch64_LDRBBpost: { // ldrb wt, [xn], #imm // LOAD results[0] = memoryData[0].zeroExtend(1, 8); - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRBBpre: { // ldrb wt, [xn, #imm]! // LOAD results[0] = memoryData[0].zeroExtend(1, 8); results[1] = - srcRegVals[0].get() + metadata.operands[1].mem.disp; + operands[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRBBroW: { // ldrb wt, @@ -3454,7 +3420,7 @@ void Instruction::execute() { uint16_t regSize = (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRBpre: // ldr bt, [xn, #imm]! @@ -3468,7 +3434,7 @@ void Instruction::execute() { (isScalarData_ || isVectorData_ || isSVEData_) ? 256 : 8; results[0] = memoryData[0].zeroExtend(dataSize_, regSize); results[1] = - srcRegVals[0].get() + metadata.operands[1].mem.disp; + operands[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRDroW: { // ldr dt, [xn, wm, {extend {#amount}}] @@ -3484,14 +3450,14 @@ void Instruction::execute() { case Opcode::AArch64_LDRHHpost: { // ldrh wt, [xn], #imm // LOAD results[0] = memoryData[0].zeroExtend(2, 8); - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRHHpre: { // ldrh wt, [xn, #imm]! // LOAD results[0] = memoryData[0].zeroExtend(2, 8); results[1] = - srcRegVals[0].get() + metadata.operands[1].mem.disp; + operands[0].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_LDRHHroW: { // ldrh wt, [xn, wm, {extend {#amount}}] @@ -3582,7 +3548,7 @@ void Instruction::execute() { case Opcode::AArch64_LDRSWpost: { // ldrsw xt, [xn], #simm // LOAD results[0] = static_cast(memoryData[0].get()); - results[1] = srcRegVals[0].get() + metadata.operands[2].imm; + results[1] = operands[0].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_LDRSWroX: { // ldrsw xt, [xn, xm{, extend @@ -3717,55 +3683,52 @@ void Instruction::execute() { } case Opcode::AArch64_LSLVWr: { // lslv wd, wn, wm results[0] = { - logicalHelp::logicalShiftLR_3ops(srcRegVals, true), 8}; + logicalHelp::logicalShiftLR_3ops(operands, true), 8}; break; } case Opcode::AArch64_LSLVXr: { // lslv xd, xn, xm - results[0] = - logicalHelp::logicalShiftLR_3ops(srcRegVals, true); + results[0] = logicalHelp::logicalShiftLR_3ops(operands, true); break; } case Opcode::AArch64_LSL_ZZI_S: { // lsl zd.s, zn.s, #imm - results[0] = - sveHelp::sveLsl_imm(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::sveLsl_imm(operands, metadata, VL_bits); break; } case Opcode::AArch64_LSRVWr: { // lsrv wd, wn, wm results[0] = { - logicalHelp::logicalShiftLR_3ops(srcRegVals, false), 8}; + logicalHelp::logicalShiftLR_3ops(operands, false), 8}; break; } case Opcode::AArch64_LSRVXr: { // lsrv xd, xn, xm results[0] = - logicalHelp::logicalShiftLR_3ops(srcRegVals, false); + logicalHelp::logicalShiftLR_3ops(operands, false); break; } case Opcode::AArch64_MADDWrrr: { // madd wd, wn, wm, wa - results[0] = {multiplyHelp::madd_4ops(srcRegVals), 8}; + results[0] = {multiplyHelp::madd_4ops(operands), 8}; break; } case Opcode::AArch64_MADDXrrr: { // madd xd, xn, xm, xa - results[0] = multiplyHelp::madd_4ops(srcRegVals); + results[0] = multiplyHelp::madd_4ops(operands); break; } case Opcode::AArch64_MLA_ZPmZZ_B: { // mla zda.b, pg/m, zn.b, zm.b - results[0] = - sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_D: { // mla zda.d, pg/m, zn.d, zm.d results[0] = - sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_H: { // mla zda.h, pg/m, zn.h, zm.h results[0] = - sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_MLA_ZPmZZ_S: { // mla zda.s, pg/m, zn.s, zm.s results[0] = - sveHelp::sveMlaPredicated_vecs(srcRegVals, VL_bits); + sveHelp::sveMlaPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_MOVID: { // movi dd, #imm @@ -3794,12 +3757,12 @@ void Instruction::execute() { } case Opcode::AArch64_MOVKWi: { // movk wd, #imm results[0] = { - arithmeticHelp::movkShift_imm(srcRegVals, metadata), 8}; + arithmeticHelp::movkShift_imm(operands, metadata), 8}; break; } case Opcode::AArch64_MOVKXi: { // movk xd, #imm results[0] = - arithmeticHelp::movkShift_imm(srcRegVals, metadata); + arithmeticHelp::movkShift_imm(operands, metadata); break; } case Opcode::AArch64_MOVNWi: { // movn wd, #imm{, LSL #shift} @@ -3815,22 +3778,22 @@ void Instruction::execute() { } case Opcode::AArch64_MOVPRFX_ZPmZ_D: { // movprfx zd.d, pg/m, zn.d results[0] = sveHelp::sveMovprfxPredicated_destUnchanged( - srcRegVals, VL_bits); + operands, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZPzZ_D: { // movprfx zd.d, pg/z, zn.d results[0] = sveHelp::sveMovprfxPredicated_destToZero( - srcRegVals, VL_bits); + operands, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZPzZ_S: { // movprfx zd.s, pg/z, zn.s results[0] = sveHelp::sveMovprfxPredicated_destToZero( - srcRegVals, VL_bits); + operands, VL_bits); break; } case Opcode::AArch64_MOVPRFX_ZZ: { // movprfx zd, zn // TODO: Adopt hint logic of the MOVPRFX instruction - results[0] = srcRegVals[0]; + results[0] = operands[0]; break; } case Opcode::AArch64_MOVZWi: { // movz wd, #imm @@ -3845,7 +3808,7 @@ void Instruction::execute() { break; } case Opcode::AArch64_MRS: { // mrs xt, (systemreg|Sop0_op1_Cn_Cm_op2) - results[0] = srcRegVals[0]; + results[0] = operands[0]; break; } case Opcode::AArch64_MSR: { // msr (systemreg|Sop0_op1_Cn_Cm_op2), xt @@ -3855,16 +3818,16 @@ void Instruction::execute() { static_cast(ARM64_SYSREG_SVCR)) { return SMZAupdated(); } else { - results[0] = srcRegVals[0]; + results[0] = operands[0]; } break; } case Opcode::AArch64_MSUBWrrr: { // msub wd, wn, wm, wa - results[0] = {multiplyHelp::msub_4ops(srcRegVals), 8}; + results[0] = {multiplyHelp::msub_4ops(operands), 8}; break; } case Opcode::AArch64_MSUBXrrr: { // msub xd, xn, xm, xa - results[0] = multiplyHelp::msub_4ops(srcRegVals); + results[0] = multiplyHelp::msub_4ops(operands); break; } case Opcode::AArch64_MSRpstatesvcrImm1: { // msr svcr, #imm @@ -3887,22 +3850,22 @@ void Instruction::execute() { } } case Opcode::AArch64_MUL_ZPmZ_B: { // mul zdn.b, pg/m, zdn.b, zm.b - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_D: { // mul zdn.d, pg/m, zdn.d, zm.d - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_H: { // mul zdn.h, pg/m, zdn.h, zm.h - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } case Opcode::AArch64_MUL_ZPmZ_S: { // mul zdn.s, pg/m, zdn.s, zm.s - results[0] = sveHelp::sveMulPredicated(srcRegVals, metadata, + results[0] = sveHelp::sveMulPredicated(operands, metadata, VL_bits, false); break; } @@ -3931,75 +3894,75 @@ void Instruction::execute() { break; } case Opcode::AArch64_NEGv2i64: { // neg vd.2d, vn.2d - results[0] = neonHelp::vecFneg_2ops(srcRegVals); + results[0] = neonHelp::vecFneg_2ops(operands); break; } case Opcode::AArch64_NOTv16i8: { // not vd.16b, vn.16b results[0] = neonHelp::vecLogicOp_2vecs( - srcRegVals, [](uint8_t x) -> uint8_t { return ~x; }); + operands, [](uint8_t x) -> uint8_t { return ~x; }); break; } case Opcode::AArch64_NOTv8i8: { // not vd.8b, vn.8b results[0] = neonHelp::vecLogicOp_2vecs( - srcRegVals, [](uint8_t x) -> uint8_t { return ~x; }); + operands, [](uint8_t x) -> uint8_t { return ~x; }); break; } case Opcode::AArch64_ORNWrs: { // orn wd, wn, wm{, shift{ #amount}} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | (~y); }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORNXrs: { // orn xd, xn, xm{, shift{ #amount}} auto [result, nzcv] = logicalHelp::logicOpShift_3ops( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | (~y); }); results[0] = result; break; } case Opcode::AArch64_ORRWri: { // orr wd, wn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORRWrs: { // orr wd, wn, wm{, shift{ #amount}} results[0] = { - comparisonHelp::orrShift_3ops(srcRegVals, metadata), 8}; + comparisonHelp::orrShift_3ops(operands, metadata), 8}; break; } case Opcode::AArch64_ORRXri: { // orr xd, xn, #imm auto [result, nzcv] = logicalHelp::logicOp_imm( - srcRegVals, metadata, false, + operands, metadata, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | y; }); results[0] = {result, 8}; break; } case Opcode::AArch64_ORRXrs: { // orr xd, xn, xm{, shift{ #amount}} results[0] = - comparisonHelp::orrShift_3ops(srcRegVals, metadata); + comparisonHelp::orrShift_3ops(operands, metadata); break; } case Opcode::AArch64_ORR_PPzPP: { // orr pd.b, pg/z, pn.b, pm.b results[0] = sveHelp::sveLogicOp_preds( - srcRegVals, VL_bits, + operands, VL_bits, [](uint64_t x, uint64_t y) -> uint64_t { return x | y; }); break; } case Opcode::AArch64_ORR_ZZZ: { // orr zd.d, zn.d, zm.d - results[0] = sveHelp::sveOrr_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveOrr_3vecs(operands, VL_bits); break; } case Opcode::AArch64_ORRv16i8: { // orr vd.16b, Vn.16b, Vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); break; } case Opcode::AArch64_ORRv8i8: { // orr vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x | y; }); break; } case Opcode::AArch64_PFALSE: { // pfalse pd.b @@ -4011,24 +3974,24 @@ void Instruction::execute() { break; } case Opcode::AArch64_PSEL_PPPRI_B: { // psel pd, pn, pm.b[wa, #imm] - results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::svePsel(operands, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_D: { // psel pd, pn, pm.d[wa, #imm] - results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::svePsel(operands, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_H: { // psel pd, pn, pm.h[wa, #imm] - results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::svePsel(operands, metadata, VL_bits); break; } case Opcode::AArch64_PSEL_PPPRI_S: { // psel pd, pn, pm.s[wa, #imm] - results[0] = sveHelp::svePsel(srcRegVals, metadata, VL_bits); + results[0] = sveHelp::svePsel(operands, metadata, VL_bits); break; } case Opcode::AArch64_PTEST_PP: { // ptest pg, pn.b - const uint64_t* g = srcRegVals[0].getAsVector(); - const uint64_t* s = srcRegVals[1].getAsVector(); + const uint64_t* g = operands[0].getAsVector(); + const uint64_t* s = operands[1].getAsVector(); std::array masked_n = {(g[0] & s[0]), (g[1] & s[1]), (g[2] & s[2]), (g[3] & s[3])}; // Byte count = 1 as destination predicate is regarding single bytes. @@ -4052,19 +4015,19 @@ void Instruction::execute() { break; } case Opcode::AArch64_PUNPKHI_PP: { // punpkhi pd.h, pn.b - results[0] = sveHelp::svePunpk(srcRegVals, VL_bits, true); + results[0] = sveHelp::svePunpk(operands, VL_bits, true); break; } case Opcode::AArch64_PUNPKLO_PP: { // punpklo pd.h, pn.b - results[0] = sveHelp::svePunpk(srcRegVals, VL_bits, false); + results[0] = sveHelp::svePunpk(operands, VL_bits, false); break; } case Opcode::AArch64_RBITWr: { // rbit wd, wn - results[0] = {bitmanipHelp::rbit(srcRegVals, metadata), 8}; + results[0] = {bitmanipHelp::rbit(operands, metadata), 8}; break; } case Opcode::AArch64_RBITXr: { // rbit xd, xn - results[0] = bitmanipHelp::rbit(srcRegVals, metadata); + results[0] = bitmanipHelp::rbit(operands, metadata); break; } case Opcode::AArch64_RDVLI_XI: { // rdvl xd, #imm @@ -4074,312 +4037,308 @@ void Instruction::execute() { } case Opcode::AArch64_RET: { // ret {xr} branchTaken_ = true; - branchAddress_ = srcRegVals[0].get(); + branchAddress_ = operands[0].get(); break; } case Opcode::AArch64_REV16v16i8: { // rev16 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV16v8i8: { // rev16 Vd.8b, Vn.8b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV32v16i8: { // rev32 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV32v4i16: { // rev32 Vd.4h, Vn.4h - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV32v8i16: { // rev32 Vd.8h, Vn.8h - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV32v8i8: { // rev32 Vd.8b, Vn.8b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v16i8: { // rev64 Vd.16b, Vn.16b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v2i32: { // rev64 Vd.2s, Vn.2s - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v4i16: { // rev64 Vd.4h, Vn.4h - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v4i32: { // rev64 Vd.4s, Vn.4s - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v8i16: { // rev64 Vd.8h, Vn.8h - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REV64v8i8: { // rev64 Vd.8b Vn.8b - results[0] = neonHelp::vecRev(srcRegVals); + results[0] = neonHelp::vecRev(operands); break; } case Opcode::AArch64_REVXr: { // rev xd, xn - results[0] = bitmanipHelp::rev(srcRegVals); + results[0] = bitmanipHelp::rev(operands); break; } case Opcode::AArch64_REV_PP_B: { // rev pd.b, pn.b - results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_predicates(operands, VL_bits); break; } case Opcode::AArch64_REV_PP_D: { // rev pd.d, pn.d - results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_predicates(operands, VL_bits); break; } case Opcode::AArch64_REV_PP_H: { // rev pd.h, pn.h - results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_predicates(operands, VL_bits); break; } case Opcode::AArch64_REV_PP_S: { // rev pd.s, pn.s - results[0] = sveHelp::sveRev_predicates(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_predicates(operands, VL_bits); break; } case Opcode::AArch64_REV_ZZ_B: { // rev zd.b, zn.b - results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_vecs(operands, VL_bits); break; } case Opcode::AArch64_REV_ZZ_D: { // rev zd.d, zn.d - results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_vecs(operands, VL_bits); break; } case Opcode::AArch64_REV_ZZ_H: { // rev zd.h, zn.h - results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_vecs(operands, VL_bits); break; } case Opcode::AArch64_REV_ZZ_S: { // rev zd.s, zn.s - results[0] = sveHelp::sveRev_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveRev_vecs(operands, VL_bits); break; } case Opcode::AArch64_RORVWr: { // rorv wd, wn, wm - results[0] = {logicalHelp::rorv_3ops(srcRegVals), 8}; + results[0] = {logicalHelp::rorv_3ops(operands), 8}; break; } case Opcode::AArch64_RORVXr: { // rorv xd, xn, xm - results[0] = logicalHelp::rorv_3ops(srcRegVals); + results[0] = logicalHelp::rorv_3ops(operands); break; } case Opcode::AArch64_SBCWr: { // sbc wd, wn, wm - results[0] = {arithmeticHelp::sbc(srcRegVals), 8}; + results[0] = {arithmeticHelp::sbc(operands), 8}; break; } case Opcode::AArch64_SBCXr: { // sbc xd, xn, xm - results[0] = arithmeticHelp::sbc(srcRegVals); + results[0] = arithmeticHelp::sbc(operands); break; } case Opcode::AArch64_SBFMWri: { // sbfm wd, wn, #immr, #imms results[0] = { - bitmanipHelp::bfm_2imms(srcRegVals, metadata, true, true), + bitmanipHelp::bfm_2imms(operands, metadata, true, true), 8}; break; } case Opcode::AArch64_SBFMXri: { // sbfm xd, xn, #immr, #imms results[0] = - bitmanipHelp::bfm_2imms(srcRegVals, metadata, true, true); + bitmanipHelp::bfm_2imms(operands, metadata, true, true); break; } case Opcode::AArch64_SCVTFSWSri: { // scvtf sd, wn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(srcRegVals, metadata); + floatHelp::scvtf_FixedPoint(operands, metadata); break; } case Opcode::AArch64_SCVTFSXDri: { // scvtf dd, xn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(srcRegVals, metadata); + floatHelp::scvtf_FixedPoint(operands, metadata); break; } case Opcode::AArch64_SCVTFSXSri: { // scvtf sd, xn, #fbits results[0] = - floatHelp::scvtf_FixedPoint(srcRegVals, metadata); + floatHelp::scvtf_FixedPoint(operands, metadata); break; } case Opcode::AArch64_SCVTFUWDri: { // scvtf dd, wn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUWSri: { // scvtf sd, wn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUXDri: { // scvtf dd, xn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTFUXSri: { // scvtf sd, xn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTF_ZPmZ_DtoD: { // scvtf zd.d, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_DtoS: { // scvtf zd.s, pg/m, zn.d results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_StoD: { // scvtf zd.d, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_SCVTF_ZPmZ_StoS: { // scvtf zd.s, pg/m, zn.s results[0] = - sveHelp::sveFcvtPredicated(srcRegVals, VL_bits); + sveHelp::sveFcvtPredicated(operands, VL_bits); break; } case Opcode::AArch64_SCVTFv1i32: { // scvtf sd, sn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTFv1i64: { // scvtf dd, dn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_SCVTFv2f32: { // scvtf vd.2s, vn.2s results[0] = neonHelp::vecScvtf_2vecs( - srcRegVals, - [](int32_t x) -> float { return static_cast(x); }); + operands, [](int32_t x) -> float { return static_cast(x); }); break; } case Opcode::AArch64_SCVTFv2f64: { // scvtf vd.2d, vn.2d results[0] = neonHelp::vecScvtf_2vecs( - srcRegVals, + operands, [](int64_t x) -> double { return static_cast(x); }); break; } case Opcode::AArch64_SCVTFv4f32: { // scvtf vd.4s, vn.4s results[0] = neonHelp::vecScvtf_2vecs( - srcRegVals, - [](int32_t x) -> float { return static_cast(x); }); + operands, [](int32_t x) -> float { return static_cast(x); }); break; } case Opcode::AArch64_SDIVWr: { // sdiv wd, wn, wm - results[0] = {divideHelp::div_3ops(srcRegVals), 8}; + results[0] = {divideHelp::div_3ops(operands), 8}; break; } case Opcode::AArch64_SDIVXr: { // sdiv xd, xn, xm - results[0] = {divideHelp::div_3ops(srcRegVals), 8}; + results[0] = {divideHelp::div_3ops(operands), 8}; break; } case Opcode::AArch64_SEL_ZPZZ_D: { // sel zd.d, pg, zn.d, zm.d - results[0] = sveHelp::sveSel_zpzz(srcRegVals, VL_bits); + results[0] = sveHelp::sveSel_zpzz(operands, VL_bits); break; } case Opcode::AArch64_SEL_ZPZZ_S: { // sel zd.s, pg, zn.s, zm.s - results[0] = sveHelp::sveSel_zpzz(srcRegVals, VL_bits); + results[0] = sveHelp::sveSel_zpzz(operands, VL_bits); break; } case Opcode::AArch64_SHLd: { // shl dd, dn #imm results[0] = - neonHelp::vecShlShift_vecImm(srcRegVals, metadata); + neonHelp::vecShlShift_vecImm(operands, metadata); break; } case Opcode::AArch64_SHLv4i32_shift: { // shl vd.4s, vn.4s, #imm results[0] = - neonHelp::vecShlShift_vecImm(srcRegVals, metadata); + neonHelp::vecShlShift_vecImm(operands, metadata); break; } case Opcode::AArch64_SMADDLrrr: { // smaddl xd, wn, wm, xa - results[0] = multiplyHelp::maddl_4ops(srcRegVals); + results[0] = multiplyHelp::maddl_4ops(operands); break; } case Opcode::AArch64_SMAX_ZI_S: { // smax zdn.s, zdn.s, #imm results[0] = - sveHelp::sveMax_vecImm(srcRegVals, metadata, VL_bits); + sveHelp::sveMax_vecImm(operands, metadata, VL_bits); break; } case Opcode::AArch64_SMAX_ZPmZ_S: { // smax zd.s, pg/m, zn.s, zm.s - results[0] = - sveHelp::sveMaxPredicated_vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveMaxPredicated_vecs(operands, VL_bits); break; } case Opcode::AArch64_SMAXv4i32: { // smax vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, + operands, [](int32_t x, int32_t y) -> int32_t { return std::max(x, y); }); break; } case Opcode::AArch64_SMINV_VPZ_S: { // sminv sd, pg, zn.s - results[0] = sveHelp::sveSminv(srcRegVals, VL_bits); + results[0] = sveHelp::sveSminv(operands, VL_bits); break; } case Opcode::AArch64_SMINVv4i32v: { // sminv sd, vn.4s - results[0] = neonHelp::vecMinv_2ops(srcRegVals); + results[0] = neonHelp::vecMinv_2ops(operands); break; } case Opcode::AArch64_SMIN_ZPmZ_S: { // smin zd.s, pg/m, zn.s, zm.s results[0] = sveHelp::sveLogicOpPredicated_3vecs( - srcRegVals, VL_bits, + operands, VL_bits, [](int32_t x, int32_t y) -> int32_t { return std::min(x, y); }); break; } case Opcode::AArch64_SMINv4i32: { // smin vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, + operands, [](int32_t x, int32_t y) -> int32_t { return std::min(x, y); }); break; } case Opcode::AArch64_SMSUBLrrr: { // smsubl xd, wn, wm, xa - results[0] = arithmeticHelp::msubl_4ops(srcRegVals); + results[0] = arithmeticHelp::msubl_4ops(operands); break; } case Opcode::AArch64_SMULH_ZPmZ_B: { // smulh zdn.b, pg/m, zdn.b, zm.b results[0] = - sveHelp::sveMulhPredicated(srcRegVals, VL_bits); + sveHelp::sveMulhPredicated(operands, VL_bits); break; } case Opcode::AArch64_SMULH_ZPmZ_H: { // smulh zdn.h, pg/m, zdn.h, zm.h results[0] = - sveHelp::sveMulhPredicated(srcRegVals, VL_bits); + sveHelp::sveMulhPredicated(operands, VL_bits); break; } case Opcode::AArch64_SMULH_ZPmZ_S: { // smulh zdn.s, pg/m, zdn.s, zm.s results[0] = - sveHelp::sveMulhPredicated(srcRegVals, VL_bits); + sveHelp::sveMulhPredicated(operands, VL_bits); break; } case Opcode::AArch64_SMULHrr: { // smulh xd, xn, xm // TODO: signed - results[0] = AuxFunc::mulhi(srcRegVals[0].get(), - srcRegVals[1].get()); + results[0] = AuxFunc::mulhi(operands[0].get(), + operands[1].get()); break; } case Opcode::AArch64_SSHLLv2i32_shift: { // sshll vd.2d, vn.2s, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, false); + operands, metadata, false); break; } case Opcode::AArch64_SSHLLv4i32_shift: { // sshll2 vd.2d, vn.4s, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, true); + operands, metadata, true); break; } case Opcode::AArch64_SHRNv8i8_shift: { // shrn vd.8b, vn.8h, #imm - results[0] = neonHelp::vecShrnShift_imm( - srcRegVals, metadata); + results[0] = neonHelp::vecShrnShift_imm(operands, + metadata); break; } case Opcode::AArch64_SSHRv4i32_shift: { // sshr vd.4s, vn.4s, #imm - results[0] = - neonHelp::vecSshrShift_imm(srcRegVals, metadata); + results[0] = neonHelp::vecSshrShift_imm(operands, metadata); break; } case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4394,8 +4353,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4410,8 +4369,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1D_IMM: { // st1d {zd.d}, pg, [zn.d{, #imm}] // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4428,8 +4387,8 @@ void Instruction::execute() { // zm.d, lsl # // 3] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4449,15 +4408,14 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; - const uint64_t* tileSlice = - srcRegVals[sliceNum].getAsVector(); + const uint64_t* tileSlice = operands[sliceNum].getAsVector(); memoryData = sveHelp::sve_merge_store_data(tileSlice, pg, VL_bits); @@ -4470,9 +4428,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 64; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -4484,7 +4442,7 @@ void Instruction::execute() { for (uint16_t x = 0; x < partition_num; x++) { uint64_t shifted_active = 1ull << ((x % 8) * 8); if (pg[x / 8] & shifted_active) { - mdata[md_size] = srcRegVals[x].getAsVector()[sliceNum]; + mdata[md_size] = operands[x].getAsVector()[sliceNum]; md_size++; } else if (md_size) { memoryData[index] = RegisterValue((char*)mdata.data(), md_size * 8); @@ -4504,15 +4462,14 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; - const uint32_t* tileSlice = - srcRegVals[sliceNum].getAsVector(); + const uint32_t* tileSlice = operands[sliceNum].getAsVector(); memoryData = sveHelp::sve_merge_store_data(tileSlice, pg, VL_bits); @@ -4525,9 +4482,9 @@ void Instruction::execute() { if (!ZAenabled) return ZAdisabled(); const uint16_t partition_num = VL_bits / 32; - const uint32_t ws = srcRegVals[partition_num].get(); + const uint32_t ws = operands[partition_num].get(); const uint64_t* pg = - srcRegVals[partition_num + 1].getAsVector(); + operands[partition_num + 1].getAsVector(); const uint32_t sliceNum = (ws + metadata.operands[0].sme_index.disp) % partition_num; @@ -4539,7 +4496,7 @@ void Instruction::execute() { for (uint16_t x = 0; x < partition_num; x++) { uint64_t shifted_active = 1ull << ((x % 16) * 4); if (pg[x / 16] & shifted_active) { - mdata[md_size] = srcRegVals[x].getAsVector()[sliceNum]; + mdata[md_size] = operands[x].getAsVector()[sliceNum]; md_size++; } else if (md_size) { memoryData[index] = RegisterValue((char*)mdata.data(), md_size * 4); @@ -4555,8 +4512,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1W_D_IMM: { // st1w {zt.d}, pg, [zn.d{, #imm}] // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; uint16_t index = 0; @@ -4571,8 +4528,8 @@ void Instruction::execute() { } case Opcode::AArch64_SST1W_IMM: { // st1w {zt.s}, pg, [zn.s{, #imm}] // STORE - const uint32_t* t = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint32_t* t = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); const uint16_t partition_num = VL_bits / 32; uint16_t index = 0; @@ -4587,32 +4544,32 @@ void Instruction::execute() { } case Opcode::AArch64_ST1B: { // st1b {zt.b}, pg, [xn, xm] // STORE - const uint8_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint8_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1B_IMM: { // st1b {zt.b}, pg, [xn{, #imm, mul vl}] // STORE - const uint8_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint8_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1D: { // st1d {zt.d}, pg, [xn, xm, lsl #3] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1D_IMM: { // st1d {zt.d}, pg, [xn{, #imm, mul vl}] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; @@ -4621,9 +4578,8 @@ void Instruction::execute() { // vt4.16b}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 16 * sizeof(uint8_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 16 * sizeof(uint8_t)); } break; } @@ -4632,24 +4588,22 @@ void Instruction::execute() { // <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 16 * sizeof(uint8_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 16 * sizeof(uint8_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? srcRegVals[5].get() + ? operands[5].get() : 64; - results[0] = srcRegVals[4].get() + postIndex; + results[0] = operands[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv2d: { // st1 {vt.2d, vt2.2d, vt3.2d, // vt4.2d}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 2 * sizeof(uint64_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 2 * sizeof(uint64_t)); } break; } @@ -4657,39 +4611,36 @@ void Instruction::execute() { // vt4.2d}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 2 * sizeof(uint64_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 2 * sizeof(uint64_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? srcRegVals[5].get() + ? operands[5].get() : 64; - results[0] = srcRegVals[4].get() + postIndex; + results[0] = operands[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv2s_POST: { // st1 {vt.2s, vt2.2s, vt3.2s, // vt4.2s}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 2 * sizeof(uint32_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 2 * sizeof(uint32_t)); } // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? srcRegVals[5].get() + ? operands[5].get() : 32; - results[0] = srcRegVals[4].get() + postIndex; + results[0] = operands[4].get() + postIndex; break; } case Opcode::AArch64_ST1Fourv4s: { // st1 {vt.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn|sp] // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 4 * sizeof(uint32_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 4 * sizeof(uint32_t)); } break; } @@ -4697,21 +4648,20 @@ void Instruction::execute() { // vt4.4s}, [xn|sp], <#imm|xm> // STORE for (int i = 0; i < 4; i++) { - memoryData[i] = - RegisterValue((char*)srcRegVals[i].getAsVector(), - 4 * sizeof(uint32_t)); + memoryData[i] = RegisterValue( + (char*)operands[i].getAsVector(), 4 * sizeof(uint32_t)); } // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata.operands[5].type == ARM64_OP_REG) - ? srcRegVals[5].get() + ? operands[5].get() : 64; - results[0] = srcRegVals[4].get() + postIndex; + results[0] = operands[4].get() + postIndex; break; } case Opcode::AArch64_ST1Twov16b: { // st1 {vt.16b, vt2.16b}, [xn|sp] // STORE - const uint8_t* t = srcRegVals[0].getAsVector(); - const uint8_t* t2 = srcRegVals[1].getAsVector(); + const uint8_t* t = operands[0].getAsVector(); + const uint8_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 16 * sizeof(uint8_t)); memoryData[1] = RegisterValue((char*)t2, 16 * sizeof(uint8_t)); break; @@ -4719,22 +4669,22 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov16b_POST: { // st1 {vt.16b, vt2.16b}, // [xn|sp], <#imm|xm> // STORE - const uint8_t* t = srcRegVals[0].getAsVector(); - const uint8_t* t2 = srcRegVals[1].getAsVector(); + const uint8_t* t = operands[0].getAsVector(); + const uint8_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 16 * sizeof(uint8_t)); memoryData[1] = RegisterValue((char*)t2, 16 * sizeof(uint8_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? srcRegVals[3].get() + ? operands[3].get() : 32; - results[0] = srcRegVals[2].get() + postIndex; + results[0] = operands[2].get() + postIndex; break; } case Opcode::AArch64_ST1Twov2d: { // st1 {vt.2d, vt2.2d}, [xn|sp] // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); - const uint64_t* t2 = srcRegVals[1].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); + const uint64_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 2 * sizeof(uint64_t)); memoryData[1] = RegisterValue((char*)t2, 2 * sizeof(uint64_t)); break; @@ -4742,22 +4692,22 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov2d_POST: { // st1 {vt.2d, vt2.2d}, // [xn|sp], <#imm|xm> // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); - const uint64_t* t2 = srcRegVals[1].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); + const uint64_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 2 * sizeof(uint64_t)); memoryData[1] = RegisterValue((char*)t2, 2 * sizeof(uint64_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? srcRegVals[3].get() + ? operands[3].get() : 32; - results[0] = srcRegVals[2].get() + postIndex; + results[0] = operands[2].get() + postIndex; break; } case Opcode::AArch64_ST1Twov4s: { // st1 {vt.4s, vt2.4s}, [xn|sp] // STORE - const uint32_t* t = srcRegVals[0].getAsVector(); - const uint32_t* t2 = srcRegVals[1].getAsVector(); + const uint32_t* t = operands[0].getAsVector(); + const uint32_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 4 * sizeof(uint32_t)); memoryData[1] = RegisterValue((char*)t2, 4 * sizeof(uint32_t)); break; @@ -4765,30 +4715,30 @@ void Instruction::execute() { case Opcode::AArch64_ST1Twov4s_POST: { // st1 {vt.4s, vt2.4s}, // [xn|sp], <#imm|xm> // STORE - const uint32_t* t = srcRegVals[0].getAsVector(); - const uint32_t* t2 = srcRegVals[1].getAsVector(); + const uint32_t* t = operands[0].getAsVector(); + const uint32_t* t2 = operands[1].getAsVector(); memoryData[0] = RegisterValue((char*)t, 4 * sizeof(uint32_t)); memoryData[1] = RegisterValue((char*)t2, 4 * sizeof(uint32_t)); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata.operands[3].type == ARM64_OP_REG) - ? srcRegVals[3].get() + ? operands[3].get() : 32; - results[0] = srcRegVals[2].get() + postIndex; + results[0] = operands[2].get() + postIndex; break; } case Opcode::AArch64_ST1W: { // st1w {zt.s}, pg, [xn, xm, lsl #2] // STORE - const uint32_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint32_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1W_D: { // st1w {zt.d}, pg, [xn, xm, lsl #2] // STORE - const uint64_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint64_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); @@ -4796,90 +4746,90 @@ void Instruction::execute() { } case Opcode::AArch64_ST1W_IMM: { // st1w {zt.s}, pg, [xn{, #imm, mul vl}] // STORE - const uint32_t* d = srcRegVals[0].getAsVector(); - const uint64_t* p = srcRegVals[1].getAsVector(); + const uint32_t* d = operands[0].getAsVector(); + const uint64_t* p = operands[1].getAsVector(); memoryData = sveHelp::sve_merge_store_data(d, p, VL_bits); break; } case Opcode::AArch64_ST1i16: { // st1 {vt.h}[index], [xn] // STORE - const uint16_t* t = srcRegVals[0].getAsVector(); + const uint16_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i16_POST: { // st1 {vt.h}[index], [xn], xm // st1 {vt.h}[index], [xn], #2 // STORE - const uint16_t* t = srcRegVals[0].getAsVector(); + const uint16_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 2; if (metadata.operandCount == 3) { - offset = srcRegVals[2].get(); + offset = operands[2].get(); } - results[0] = srcRegVals[1].get() + offset; + results[0] = operands[1].get() + offset; break; } case Opcode::AArch64_ST1i32: { // st1 {vt.s}[index], [xn] // STORE - const uint32_t* t = srcRegVals[0].getAsVector(); + const uint32_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i32_POST: { // st1 {vt.s}[index], [xn], xm // st1 {vt.s}[index], [xn], #4 // STORE - const uint32_t* t = srcRegVals[0].getAsVector(); + const uint32_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 4; if (metadata.operandCount == 3) { - offset = srcRegVals[2].get(); + offset = operands[2].get(); } - results[0] = srcRegVals[1].get() + offset; + results[0] = operands[1].get() + offset; break; } case Opcode::AArch64_ST1i64: { // st1 {vt.d}[index], [xn] // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i64_POST: { // st1 {vt.d}[index], [xn], xm // st1 {vt.d}[index], [xn], #8 // STORE - const uint64_t* t = srcRegVals[0].getAsVector(); + const uint64_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 8; if (metadata.operandCount == 3) { - offset = srcRegVals[2].get(); + offset = operands[2].get(); } - results[0] = srcRegVals[1].get() + offset; + results[0] = operands[1].get() + offset; break; } case Opcode::AArch64_ST1i8: { // st1 {vt.b}[index], [xn] // STORE - const uint8_t* t = srcRegVals[0].getAsVector(); + const uint8_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; break; } case Opcode::AArch64_ST1i8_POST: { // st1 {vt.b}[index], [xn], xm // st1 {vt.b}[index], [xn], #1 // STORE - const uint8_t* t = srcRegVals[0].getAsVector(); + const uint8_t* t = operands[0].getAsVector(); memoryData[0] = t[metadata.operands[0].vector_index]; uint64_t offset = 1; if (metadata.operandCount == 3) { - offset = srcRegVals[2].get(); + offset = operands[2].get(); } - results[0] = RegisterValue(srcRegVals[1].get() + offset, 8); + results[0] = RegisterValue(operands[1].get() + offset, 8); break; } case Opcode::AArch64_ST2D_IMM: { // st2d {zt1.d, zt2.d}, pg, [{, // #imm, mul vl}] // STORE - const uint64_t* d1 = srcRegVals[0].getAsVector(); - const uint64_t* d2 = srcRegVals[1].getAsVector(); - const uint64_t* p = srcRegVals[2].getAsVector(); + const uint64_t* d1 = operands[0].getAsVector(); + const uint64_t* d2 = operands[1].getAsVector(); + const uint64_t* p = operands[2].getAsVector(); std::vector memData; bool inActiveBlock = false; @@ -4913,8 +4863,8 @@ void Instruction::execute() { case Opcode::AArch64_ST2Twov4s_POST: { // st2 {vt1.4s, vt2.4s}, [xn], // #imm // STORE - const float* t1 = srcRegVals[0].getAsVector(); - const float* t2 = srcRegVals[1].getAsVector(); + const float* t1 = operands[0].getAsVector(); + const float* t2 = operands[1].getAsVector(); std::vector m1 = {t1[0], t2[0], t1[1], t2[1]}; std::vector m2 = {t1[2], t2[2], t1[3], t2[3]}; memoryData[0] = RegisterValue((char*)m1.data(), 4 * sizeof(float)); @@ -4922,26 +4872,26 @@ void Instruction::execute() { uint64_t offset = 32; if (metadata.operandCount == 4) { - offset = srcRegVals[3].get(); + offset = operands[3].get(); } - results[0] = srcRegVals[2].get() + offset; + results[0] = operands[2].get() + offset; break; } case Opcode::AArch64_STLRB: { // stlrb wt, [xn] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STLRW: // stlr wt, [xn] case Opcode::AArch64_STLRX: { // stlr xt, [xn] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STLXRW: // stlxr ws, wt, [xn] case Opcode::AArch64_STLXRX: { // stlxr ws, xt, [xn] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; @@ -4951,8 +4901,8 @@ void Instruction::execute() { case Opcode::AArch64_STPSi: // stp st1, st2, [xn, #imm] case Opcode::AArch64_STPWi: // stp wt1, wt2, [xn, #imm] case Opcode::AArch64_STPXi: { // stp xt1, xt2, [xn, #imm] - memoryData[0] = srcRegVals[0]; - memoryData[1] = srcRegVals[1]; + memoryData[0] = operands[0]; + memoryData[1] = operands[1]; break; } case Opcode::AArch64_STPDpost: // stp dt1, dt2, [xn], #imm @@ -4960,9 +4910,9 @@ void Instruction::execute() { case Opcode::AArch64_STPSpost: // stp st1, st2, [xn], #imm case Opcode::AArch64_STPWpost: // stp wt1, wt2, [xn], #imm case Opcode::AArch64_STPXpost: { // stp xt1, xt2, [xn], #imm - memoryData[0] = srcRegVals[0]; - memoryData[1] = srcRegVals[1]; - results[0] = srcRegVals[2].get() + metadata.operands[3].imm; + memoryData[0] = operands[0]; + memoryData[1] = operands[1]; + results[0] = operands[2].get() + metadata.operands[3].imm; break; } case Opcode::AArch64_STPDpre: // stp dt1, dt2, [xn, #imm]! @@ -4970,40 +4920,40 @@ void Instruction::execute() { case Opcode::AArch64_STPSpre: // stp st1, st2, [xn, #imm]! case Opcode::AArch64_STPWpre: // stp wt1, wt2, [xn, #imm]! case Opcode::AArch64_STPXpre: { // stp xt1, xt2, [xn, #imm]! - memoryData[0] = srcRegVals[0]; - memoryData[1] = srcRegVals[1]; + memoryData[0] = operands[0]; + memoryData[1] = operands[1]; results[0] = - srcRegVals[2].get() + metadata.operands[2].mem.disp; + operands[2].get() + metadata.operands[2].mem.disp; break; } case Opcode::AArch64_STRBBpost: { // strb wd, [xn], #imm // STORE - memoryData[0] = srcRegVals[0]; - results[0] = srcRegVals[1].get() + metadata.operands[2].imm; + memoryData[0] = operands[0]; + results[0] = operands[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRBBpre: { // strb wd, [xn, #imm]! // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; results[0] = - srcRegVals[1].get() + metadata.operands[1].mem.disp; + operands[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRBBroW: { // strb wd, // [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRBBroX: { // strb wd, // [xn, xm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRBBui: { // strb wd, [xn, #imm] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRBui: // str bt, [xn, #imm] @@ -5013,7 +4963,7 @@ void Instruction::execute() { case Opcode::AArch64_STRSui: // str st, [xn, #imm] case Opcode::AArch64_STRWui: // str wt, [xn, #imm] case Opcode::AArch64_STRXui: { // str xt, [xn, #imm] - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRBpost: // str bt, [xn], #imm @@ -5023,8 +4973,8 @@ void Instruction::execute() { case Opcode::AArch64_STRSpost: // str st, [xn], #imm case Opcode::AArch64_STRWpost: // str wt, [xn], #imm case Opcode::AArch64_STRXpost: { // str xt, [xn], #imm - memoryData[0] = srcRegVals[0]; - results[0] = srcRegVals[1].get() + metadata.operands[2].imm; + memoryData[0] = operands[0]; + results[0] = operands[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRBpre: // str bt, [xn, #imm]! @@ -5034,110 +4984,110 @@ void Instruction::execute() { case Opcode::AArch64_STRSpre: // str st, [xn, #imm]! case Opcode::AArch64_STRWpre: // str wt, [xn, #imm]! case Opcode::AArch64_STRXpre: { // str xt, [xn, #imm]! - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; results[0] = - srcRegVals[1].get() + metadata.operands[1].mem.disp; + operands[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRDroW: { // str dt, [xn, wm{, #extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRDroX: { // str dt, [xn, xm{, #extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRHHpost: { // strh wt, [xn], #imm // STORE - memoryData[0] = srcRegVals[0]; - results[0] = srcRegVals[1].get() + metadata.operands[2].imm; + memoryData[0] = operands[0]; + results[0] = operands[1].get() + metadata.operands[2].imm; break; } case Opcode::AArch64_STRHHpre: { // strh wd, [xn, #imm]! // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; results[0] = - srcRegVals[1].get() + metadata.operands[1].mem.disp; + operands[1].get() + metadata.operands[1].mem.disp; break; } case Opcode::AArch64_STRHHroW: { // strh wd, // [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRHHroX: { // strh wd, // [xn, xm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRHHui: { // strh wt, [xn, #imm] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRQroX: { // str qt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRSroW: { // str st, [xn, wm{, #extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRSroX: { // str st, [xn, xm{, #extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRWroW: { // str wd, [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRWroX: { // str wt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRXroW: { // str xd, [xn, wm{, extend {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STRXroX: { // str xt, [xn, xm{, extend, {#amount}}] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STR_PXI: { // str pt, [xn{, #imm, mul vl}] // STORE const uint64_t PL_bits = VL_bits / 8; const uint16_t partition_num = PL_bits / 8; - const uint8_t* p = srcRegVals[0].getAsVector(); + const uint8_t* p = operands[0].getAsVector(); memoryData[0] = RegisterValue((char*)p, partition_num); break; } case Opcode::AArch64_STR_ZXI: { // str zt, [xn{, #imm, mul vl}] // STORE const uint16_t partition_num = VL_bits / 8; - const uint8_t* z = srcRegVals[0].getAsVector(); + const uint8_t* z = operands[0].getAsVector(); memoryData[0] = RegisterValue((char*)z, partition_num); break; } case Opcode::AArch64_STURBBi: { // sturb wd, [xn, #imm] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STURDi: // stur dt, [xn, #imm] case Opcode::AArch64_STURHHi: { // sturh wt, [xn, #imm] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STURQi: // stur qt, [xn, #imm] @@ -5145,157 +5095,151 @@ void Instruction::execute() { case Opcode::AArch64_STURWi: // stur wt, [xn, #imm] case Opcode::AArch64_STURXi: { // stur xt, [xn, #imm] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::AArch64_STXRW: { // stxr ws, wt, [xn] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; } case Opcode::AArch64_STXRX: { // stxr ws, xt, [xn] // STORE - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; // TODO: Implement atomic memory access results[0] = static_cast(0); break; } case Opcode::AArch64_SUBSWri: { // subs wd, wn, #imm auto [result, nzcv] = - arithmeticHelp::subShift_imm(srcRegVals, metadata, true); + arithmeticHelp::subShift_imm(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSWrs: { // subs wd, wn, wm{, shift #amount} auto [result, nzcv] = - arithmeticHelp::subShift_3ops(srcRegVals, metadata, true); + arithmeticHelp::subShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSWrx: { // subs wd, wn, wm{, extend #amount} - auto [result, nzcv] = arithmeticHelp::subExtend_3ops( - srcRegVals, metadata, true); + auto [result, nzcv] = + arithmeticHelp::subExtend_3ops(operands, metadata, true); results[0] = nzcv; results[1] = {result, 8}; break; } case Opcode::AArch64_SUBSXri: { // subs xd, xn, #imm auto [result, nzcv] = - arithmeticHelp::subShift_imm(srcRegVals, metadata, true); + arithmeticHelp::subShift_imm(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBSXrs: { // subs xd, xn, xm{, shift #amount} auto [result, nzcv] = - arithmeticHelp::subShift_3ops(srcRegVals, metadata, true); + arithmeticHelp::subShift_3ops(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBSXrx: // subs xd, xn, wm{, extend #amount} case Opcode::AArch64_SUBSXrx64: { // subs xd, xn, xm{, extend #amount} - auto [result, nzcv] = arithmeticHelp::subExtend_3ops( - srcRegVals, metadata, true); + auto [result, nzcv] = + arithmeticHelp::subExtend_3ops(operands, metadata, true); results[0] = nzcv; results[1] = result; break; } case Opcode::AArch64_SUBWri: { // sub wd, wn, #imm{, } auto [result, nzcv] = - arithmeticHelp::subShift_imm(srcRegVals, metadata, false); + arithmeticHelp::subShift_imm(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_SUBWrs: { // sub wd, wn, wm{, shift #amount} - auto [result, nzcv] = arithmeticHelp::subShift_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::subShift_3ops(operands, metadata, false); results[0] = {result, 8}; break; } case Opcode::AArch64_SUBXri: { // sub xd, xn, #imm{, } auto [result, nzcv] = - arithmeticHelp::subShift_imm(srcRegVals, metadata, false); + arithmeticHelp::subShift_imm(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUBXrs: { // sub xd, xn, xm{, shift #amount} - auto [result, nzcv] = arithmeticHelp::subShift_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::subShift_3ops(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUBXrx: // sub xd, xn, wm{, extend #amount} case Opcode::AArch64_SUBXrx64: { // sub xd, xn, xm{, extend #amount} - auto [result, nzcv] = arithmeticHelp::subExtend_3ops( - srcRegVals, metadata, false); + auto [result, nzcv] = + arithmeticHelp::subExtend_3ops(operands, metadata, false); results[0] = result; break; } case Opcode::AArch64_SUB_ZZZ_B: { // sub zd.b, zn.b, zm.b - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_D: { // sub zd.d, zn.d, zm.d - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_H: { // sub zd.h, zn.h, zm.h - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_SUB_ZZZ_S: { // sub zd.s, zn.s, zm.s - results[0] = sveHelp::sveSub_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveSub_3vecs(operands, VL_bits); break; } case Opcode::AArch64_SUBv16i8: { // sub vd.16b, vn.16b, vm.16b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); break; } case Opcode::AArch64_SUBv1i64: { // sub dd, dn, dm results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); + operands, [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); break; } case Opcode::AArch64_SUBv2i32: { // sub vd.2s, vn.2s, vm.2s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); + operands, [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); break; } case Opcode::AArch64_SUBv2i64: { // sub vd.2d, vn.2d, vm.2d results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); + operands, [](uint64_t x, uint64_t y) -> uint64_t { return x - y; }); break; } case Opcode::AArch64_SUBv4i16: { // sub vd.4h, vn.4h, vm.4h results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint64_t x, uint16_t y) -> uint16_t { return x - y; }); + operands, [](uint64_t x, uint16_t y) -> uint16_t { return x - y; }); break; } case Opcode::AArch64_SUBv4i32: { // sub vd.4s, vn.4s, vm.4s results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); + operands, [](uint32_t x, uint32_t y) -> uint32_t { return x - y; }); break; } case Opcode::AArch64_SUBv8i16: { // sub vd.8h, vn.8h, vm.8h results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, - [](uint16_t x, uint16_t y) -> uint16_t { return x - y; }); + operands, [](uint16_t x, uint16_t y) -> uint16_t { return x - y; }); break; } case Opcode::AArch64_SUBv8i8: { // sub vd.8b, vn.8b, vm.8b results[0] = neonHelp::vecLogicOp_3vecs( - srcRegVals, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); + operands, [](uint8_t x, uint8_t y) -> uint8_t { return x - y; }); break; } case Opcode::AArch64_SVC: { // svc #imm @@ -5305,7 +5249,7 @@ void Instruction::execute() { } case Opcode::AArch64_SXTW_ZPmZ_D: { // sxtw zd.d, pg/m, zn.d results[0] = - sveHelp::sveSxtPredicated(srcRegVals, VL_bits); + sveHelp::sveSxtPredicated(operands, VL_bits); break; } case Opcode::AArch64_SYSxt: { // sys #, cn, cm, #{, xt} @@ -5323,465 +5267,465 @@ void Instruction::execute() { } case Opcode::AArch64_TBLv16i8Four: { // tbl Vd.16b {Vn.16b, Vn+1.16b, // Vn+2.16b,Vn+3.16b } Vm.16b - results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<16>(operands, metadata); break; } case Opcode::AArch64_TBLv16i8One: { // tbl Vd.16b {Vn.16b} Vm.16b - results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<16>(operands, metadata); break; } case Opcode::AArch64_TBLv16i8Three: { // tbl Vd.16b {Vn.16b, Vn+1.16b, // Vn+2.16b } Vm.16b - results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<16>(operands, metadata); break; } case Opcode::AArch64_TBLv16i8Two: { // tbl Vd.16b {Vn.16b, Vn+1.16b } // Vm.16b - results[0] = neonHelp::vecTbl<16>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<16>(operands, metadata); break; } case Opcode::AArch64_TBLv8i8Four: { // tbl Vd.8b {Vn.16b, Vn+1.16b, // Vn+2.16b,Vn+3.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<8>(operands, metadata); break; } case Opcode::AArch64_TBLv8i8One: { // tbl Vd.8b {Vn.16b} Vm.8b - results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<8>(operands, metadata); break; } case Opcode::AArch64_TBLv8i8Three: { // tbl Vd.8b {Vn.16b, Vn+1.16b, // Vn+2.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<8>(operands, metadata); break; } case Opcode::AArch64_TBLv8i8Two: { // tbl Vd.8b {Vn.16b, Vn+1.16b } Vm.8b - results[0] = neonHelp::vecTbl<8>(srcRegVals, metadata); + results[0] = neonHelp::vecTbl<8>(operands, metadata); break; } case Opcode::AArch64_TBNZW: { // tbnz wn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - srcRegVals, metadata, instructionAddress_, true); + operands, metadata, instructionAddress_, true); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBNZX: { // tbnz xn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - srcRegVals, metadata, instructionAddress_, true); + operands, metadata, instructionAddress_, true); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBZW: { // tbz wn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - srcRegVals, metadata, instructionAddress_, false); + operands, metadata, instructionAddress_, false); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TBZX: { // tbz xn, #imm, label auto [taken, addr] = conditionalHelp::tbnz_tbz( - srcRegVals, metadata, instructionAddress_, false); + operands, metadata, instructionAddress_, false); branchTaken_ = taken; branchAddress_ = addr; break; } case Opcode::AArch64_TRN1_ZZZ_B: { // trn1 zd.b, zn.b, zm.b - results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_D: { // trn1 zd.d, zn.d, zm.d - results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_H: { // trn1 zd.h, zn.h, zm.h - results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN1_ZZZ_S: { // trn1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveTrn1_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn1_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN1v16i8: { // trn1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v2i32: { // trn1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v2i64: { // trn1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v4i16: { // trn1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v4i32: { // trn1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v8i16: { // trn1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN1v8i8: { // trn1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecTrn1(srcRegVals); + results[0] = neonHelp::vecTrn1(operands); break; } case Opcode::AArch64_TRN2_ZZZ_B: { // trn2 zd.b, zn.b, zm.b - results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_D: { // trn2 zd.d, zn.d, zm.d - results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_H: { // trn2 zd.h, zn.h, zm.h - results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN2_ZZZ_S: { // trn2 zd.s, zn.s, zm.s - results[0] = sveHelp::sveTrn2_3vecs(srcRegVals, VL_bits); + results[0] = sveHelp::sveTrn2_3vecs(operands, VL_bits); break; } case Opcode::AArch64_TRN2v16i8: { // trn2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v2i32: { // trn2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v2i64: { // trn2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v4i16: { // trn2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v4i32: { // trn2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v8i16: { // trn2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_TRN2v8i8: { // trn2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecTrn2(srcRegVals); + results[0] = neonHelp::vecTrn2(operands); break; } case Opcode::AArch64_UADDV_VPZ_B: { // uaddv dd, pg, zn.b - results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_D: { // uaddv dd, pg, zn.d - results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_H: { // uaddv dd, pg, zn.h - results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); break; } case Opcode::AArch64_UADDV_VPZ_S: { // uaddv dd, pg, zn.s - results[0] = sveHelp::sveAddvPredicated(srcRegVals, VL_bits); + results[0] = sveHelp::sveAddvPredicated(operands, VL_bits); break; } case Opcode::AArch64_UBFMWri: { // ubfm wd, wn, #immr, #imms - results[0] = {bitmanipHelp::bfm_2imms(srcRegVals, metadata, - false, true), - 8}; + results[0] = { + bitmanipHelp::bfm_2imms(operands, metadata, false, true), + 8}; break; } case Opcode::AArch64_UBFMXri: { // ubfm xd, xn, #immr, #imms - results[0] = bitmanipHelp::bfm_2imms(srcRegVals, metadata, - false, true); + results[0] = + bitmanipHelp::bfm_2imms(operands, metadata, false, true); break; } case Opcode::AArch64_UCVTFUWDri: { // ucvtf dd, wn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUWSri: { // ucvtf sd, wn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUXDri: { // ucvtf dd, xn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UCVTFUXSri: { // ucvtf sd, xn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UCVTFv1i32: { // ucvtf sd, sn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UCVTFv1i64: { // ucvtf dd, dn - results[0] = {static_cast(srcRegVals[0].get()), 256}; + results[0] = {static_cast(operands[0].get()), 256}; break; } case Opcode::AArch64_UDIVWr: { // udiv wd, wn, wm - results[0] = {divideHelp::div_3ops(srcRegVals), 8}; + results[0] = {divideHelp::div_3ops(operands), 8}; break; } case Opcode::AArch64_UDIVXr: { // udiv xd, xn, xm - results[0] = {divideHelp::div_3ops(srcRegVals), 8}; + results[0] = {divideHelp::div_3ops(operands), 8}; break; } case Opcode::AArch64_UMADDLrrr: { // umaddl xd, wn, wm, xa - results[0] = multiplyHelp::maddl_4ops(srcRegVals); + results[0] = multiplyHelp::maddl_4ops(operands); break; } case Opcode::AArch64_UMAXPv16i8: { // umaxp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUMaxP(srcRegVals); + results[0] = neonHelp::vecUMaxP(operands); break; } case Opcode::AArch64_UMINPv16i8: { // uminp vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUMinP(srcRegVals); + results[0] = neonHelp::vecUMinP(operands); break; } case Opcode::AArch64_UMOVvi32_idx0: // umov wd, vn.s[0] case Opcode::AArch64_UMOVvi32: { // umov wd, vn.s[index] - const uint32_t* vec = srcRegVals[0].getAsVector(); + const uint32_t* vec = operands[0].getAsVector(); results[0] = {vec[metadata.operands[1].vector_index], 8}; break; } case Opcode::AArch64_UMOVvi64_idx0: // umov xd, vn.d[0] case Opcode::AArch64_UMOVvi64: { // umov xd, vn.d[index] - const uint64_t* vec = srcRegVals[0].getAsVector(); + const uint64_t* vec = operands[0].getAsVector(); results[0] = vec[metadata.operands[1].vector_index]; break; } case Opcode::AArch64_UMOVvi8_idx0: // umov wd, vn.b[0] case Opcode::AArch64_UMOVvi8: { // umov wd, vn.b[index] - const uint8_t* vec = srcRegVals[0].getAsVector(); + const uint8_t* vec = operands[0].getAsVector(); results[0] = {vec[metadata.operands[1].vector_index], 8}; break; } case Opcode::AArch64_UMSUBLrrr: { // umsubl xd, wn, wm, xa - results[0] = arithmeticHelp::msubl_4ops(srcRegVals); + results[0] = arithmeticHelp::msubl_4ops(operands); break; } case Opcode::AArch64_UMULHrr: { // umulh xd, xn, xm - results[0] = AuxFunc::mulhi(srcRegVals[0].get(), - srcRegVals[1].get()); + results[0] = AuxFunc::mulhi(operands[0].get(), + operands[1].get()); break; } case Opcode::AArch64_UQDECD_WPiI: { // uqdecd wd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); + sveHelp::sveUqdec(operands, metadata, VL_bits); break; } case Opcode::AArch64_UQDECD_XPiI: { // uqdecd xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); + sveHelp::sveUqdec(operands, metadata, VL_bits); break; } case Opcode::AArch64_UQDECH_XPiI: { // uqdech xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); + sveHelp::sveUqdec(operands, metadata, VL_bits); break; } case Opcode::AArch64_UQDECW_XPiI: { // uqdecw xd{, pattern{, MUL #imm}} results[0] = - sveHelp::sveUqdec(srcRegVals, metadata, VL_bits); + sveHelp::sveUqdec(operands, metadata, VL_bits); break; } case Opcode::AArch64_USHLLv16i8_shift: { // ushll2 vd.8h, vn.16b, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, true); + operands, metadata, true); break; } case Opcode::AArch64_USHLLv4i16_shift: { // ushll vd.4s, vn.4h, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, false); + operands, metadata, false); break; } case Opcode::AArch64_USHLLv8i16_shift: { // ushll2 vd.4s, vn.8h, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, true); + operands, metadata, true); break; } case Opcode::AArch64_USHLLv8i8_shift: { // ushll vd.8h, vn.8b, #imm results[0] = neonHelp::vecShllShift_vecImm( - srcRegVals, metadata, false); + operands, metadata, false); break; } case Opcode::AArch64_UUNPKHI_ZZ_D: { // uunpkhi zd.d, zn.s - results[0] = sveHelp::sveUnpk_vecs(srcRegVals, - VL_bits, true); + results[0] = + sveHelp::sveUnpk_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_UUNPKHI_ZZ_H: { // uunpkhi zd.h, zn.b results[0] = - sveHelp::sveUnpk_vecs(srcRegVals, VL_bits, true); + sveHelp::sveUnpk_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_UUNPKHI_ZZ_S: { // uunpkhi zd.s, zn.h - results[0] = sveHelp::sveUnpk_vecs(srcRegVals, - VL_bits, true); + results[0] = + sveHelp::sveUnpk_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_UUNPKLO_ZZ_D: { // uunpklo zd.d, zn.s - results[0] = sveHelp::sveUnpk_vecs(srcRegVals, - VL_bits, false); + results[0] = + sveHelp::sveUnpk_vecs(operands, VL_bits, false); break; } case Opcode::AArch64_UUNPKLO_ZZ_H: { // uunpklo zd.h, zn.b - results[0] = sveHelp::sveUnpk_vecs(srcRegVals, - VL_bits, false); + results[0] = + sveHelp::sveUnpk_vecs(operands, VL_bits, false); break; } case Opcode::AArch64_UUNPKLO_ZZ_S: { // uunpklo zd.s, zn.h - results[0] = sveHelp::sveUnpk_vecs(srcRegVals, - VL_bits, false); + results[0] = + sveHelp::sveUnpk_vecs(operands, VL_bits, false); break; } case Opcode::AArch64_UZP1_ZZZ_S: { // uzp1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveUzp_vecs(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveUzp_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_UZP1v16i8: { // uzp1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v2i32: { // uzp1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v2i64: { // uzp1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v4i16: { // uzp1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v4i32: { // uzp1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v8i16: { // uzp1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP1v8i8: { // uzp1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecUzp(srcRegVals, true); + results[0] = neonHelp::vecUzp(operands, true); break; } case Opcode::AArch64_UZP2v16i8: { // uzp2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v2i32: { // uzp2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v2i64: { // uzp2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v4i16: { // uzp2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v4i32: { // uzp2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v8i16: { // uzp2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_UZP2v8i8: { // uzp2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecUzp(srcRegVals, false); + results[0] = neonHelp::vecUzp(operands, false); break; } case Opcode::AArch64_WHILELO_PWW_B: { // whilelo pd.b, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_D: { // whilelo pd.d, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_H: { // whilelo pd.h, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PWW_S: { // whilelo pd.s, wn, wm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_B: { // whilelo pd.b, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_D: { // whilelo pd.d, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_H: { // whilelo pd.h, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELO_PXX_S: { // whilelo pd.s, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_B: { // whilelt pd.b, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_D: { // whilelt pd.d, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_H: { // whilelt pd.h, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; } case Opcode::AArch64_WHILELT_PXX_S: { // whilelt pd.s, xn, xm auto [output, nzcv] = - sveHelp::sveWhilelo(srcRegVals, VL_bits, true); + sveHelp::sveWhilelo(operands, VL_bits, true); results[0] = nzcv; results[1] = output; break; @@ -5791,122 +5735,119 @@ void Instruction::execute() { break; } case Opcode::AArch64_XTNv2i32: { // xtn vd.2s, vn.2d - results[0] = neonHelp::vecXtn(srcRegVals, false); + results[0] = neonHelp::vecXtn(operands, false); break; } case Opcode::AArch64_XTNv4i16: { // xtn vd.4h, vn.4s - results[0] = neonHelp::vecXtn(srcRegVals, false); + results[0] = neonHelp::vecXtn(operands, false); break; } case Opcode::AArch64_XTNv4i32: { // xtn2 vd.4s, vn.2d - results[0] = neonHelp::vecXtn(srcRegVals, true); + results[0] = neonHelp::vecXtn(operands, true); break; } case Opcode::AArch64_ZIP1_PPP_B: { // zip1 pd.b, pn.b, pm.b - results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_D: { // zip1 pd.d, pn.d, pm.d - results[0] = - sveHelp::sveZip_preds(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_H: { // zip1 pd.h, pn.h, pm.h - results[0] = - sveHelp::sveZip_preds(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1_PPP_S: { // zip1 pd.s, pn.s, pm.s - results[0] = - sveHelp::sveZip_preds(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1_ZZZ_D: { // zip1 zd.d, zn.d, zm.d - results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_vecs(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1_ZZZ_S: { // zip1 zd.s, zn.s, zm.s - results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, false); + results[0] = sveHelp::sveZip_vecs(operands, VL_bits, false); break; } case Opcode::AArch64_ZIP1v16i8: { // zip1 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v2i32: { // zip1 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v2i64: { // zip1 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v4i16: { // zip1 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v4i32: { // zip1 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v8i16: { // zip1 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP1v8i8: { // zip1 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecZip(srcRegVals, false); + results[0] = neonHelp::vecZip(operands, false); break; } case Opcode::AArch64_ZIP2_PPP_B: { // zip2 pd.b, pn.b, pm.b - results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_D: { // zip2 pd.d, pn.d, pm.d - results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_H: { // zip2 pd.h, pn.h, pm.h - results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2_PPP_S: { // zip2 pd.s, pn.s, pm.s - results[0] = sveHelp::sveZip_preds(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_preds(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2_ZZZ_D: { // zip2 zd.d, zn.d, zm.d - results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2_ZZZ_S: { // zip2 zd.s, zn.s, zm.s - results[0] = sveHelp::sveZip_vecs(srcRegVals, VL_bits, true); + results[0] = sveHelp::sveZip_vecs(operands, VL_bits, true); break; } case Opcode::AArch64_ZIP2v16i8: { // zip2 vd.16b, vn.16b, vm.16b - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v2i32: { // zip2 vd.2s, vn.2s, vm.2s - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v2i64: { // zip2 vd.2d, vn.2d, vm.2d - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v4i16: { // zip2 vd.4h, vn.4h, vm.4h - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v4i32: { // zip2 vd.4s, vn.4s, vm.4s - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v8i16: { // zip2 vd.8h, vn.8h, vm.8h - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZIP2v8i8: { // zip2 vd.8b, vn.8b, vm.8b - results[0] = neonHelp::vecZip(srcRegVals, true); + results[0] = neonHelp::vecZip(operands, true); break; } case Opcode::AArch64_ZERO_M: { // zero {mask} diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 8ed8fc4976..df06acaaa9 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -36,7 +36,7 @@ const span Instruction::getSourceRegisters() const { } const span Instruction::getSourceOperands() const { - return {const_cast(srcRegVals.data()), srcRegVals.size()}; + return {const_cast(operands.data()), operands.size()}; } const span Instruction::getDestinationRegisters() const { @@ -45,7 +45,7 @@ const span Instruction::getDestinationRegisters() const { } bool Instruction::isOperandReady(int index) const { - return static_cast(srcRegVals[index]); + return static_cast(operands[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { @@ -61,7 +61,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { assert(value.size() > 0 && "Attempted to provide an uninitialised RegisterValue"); - srcRegVals[i] = value; + operands[i] = value; numSrcOpsPending--; } diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 77d51119fa..300354cd4e 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -19,31 +19,31 @@ span Instruction::generateAddresses() { assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = srcRegVals[1].get(); + address = operands[1].get(); } else if (isLoad() && isAtomic()) { // Load reserved // Metadata operand[1] corresponds to instruction sourceRegValues[0] assert(metadata.operands[1].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = srcRegVals[0].get(); + address = operands[0].get(); } else if (isStoreAddress() && isAtomic()) { // Store conditional assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); - address = srcRegVals[1].get(); + address = operands[1].get(); } else if (isLoad()) { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - address = srcRegVals[0].get() + imm; + address = operands[0].get() + imm; } else { assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); - address = srcRegVals[1].get() + imm; + address = operands[1].get() + imm; } // Atomics @@ -109,7 +109,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_W_RL: [[fallthrough]]; case Opcode::RISCV_LR_W_AQ_RL: { - setMemoryAddresses({{srcRegVals[0].get(), 4}}); + setMemoryAddresses({{operands[0].get(), 4}}); break; } case Opcode::RISCV_LR_D: @@ -119,7 +119,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_LR_D_RL: [[fallthrough]]; case Opcode::RISCV_LR_D_AQ_RL: { - setMemoryAddresses({{srcRegVals[0].get(), 8}}); + setMemoryAddresses({{operands[0].get(), 8}}); break; } case Opcode::RISCV_SC_W: @@ -129,7 +129,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_W_RL: [[fallthrough]]; case Opcode::RISCV_SC_W_AQ_RL: { - setMemoryAddresses({{srcRegVals[1].get(), 4}}); + setMemoryAddresses({{operands[1].get(), 4}}); break; } case Opcode::RISCV_SC_D: @@ -139,7 +139,7 @@ span Instruction::generateAddresses() { case Opcode::RISCV_SC_D_RL: [[fallthrough]]; case Opcode::RISCV_SC_D_AQ_RL: { - setMemoryAddresses({{srcRegVals[1].get(), 8}}); + setMemoryAddresses({{operands[1].get(), 8}}); break; } default: diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index ef88260675..cb48916891 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -150,7 +150,7 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); + operands[sourceRegisterCount] = RegisterValue(0, 8); } else { numSrcOpsPending++; } @@ -192,7 +192,7 @@ void Instruction::decode() { if (sourceRegisters[sourceRegisterCount] == Instruction::ZERO_REGISTER) { // Catch zero register references and pre-complete those operands - srcRegVals[sourceRegisterCount] = RegisterValue(0, 8); + operands[sourceRegisterCount] = RegisterValue(0, 8); } else { numSrcOpsPending++; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 75286f0f63..8bf3eecd9d 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -221,137 +221,137 @@ void Instruction::execute() { case Opcode::RISCV_SW: // SW rs1,rs2,imm [[fallthrough]]; case Opcode::RISCV_SD: { // SD rs1,rs2,imm - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::RISCV_SLL: { // SLL rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); const int64_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLW: { // SLLW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); const int32_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits int64_t out = signExtendW(static_cast(rs1 << rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); const int32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRL: { // SRL rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLW: { // SRLW rd,rs1,rs2 - const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs1 = operands[0].get(); const uint32_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt - const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs1 = operands[0].get(); const uint32_t shamt = imm & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRA: { // SRA rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); const int64_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); const int64_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAW: { // SRAW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); const int32_t rs2 = - srcRegVals[1].get() & 63; // Only use lowest 6 bits + operands[1].get() & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); const int32_t shamt = imm & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADD: { // ADD rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDW: { // ADDW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); - const int32_t rs2 = srcRegVals[1].get(); + const int32_t rs1 = operands[0].get(); + const int32_t rs2 = operands[1].get(); int64_t out = static_cast(static_cast(rs1 + rs2)); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = imm; uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); const int32_t sourceImm = imm; uint64_t out = signExtendW(rs1 + sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUB: { // SUB rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); uint64_t out = static_cast(rs1 - rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SUBW: { // SUBW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); - const int32_t rs2 = srcRegVals[1].get(); + const int32_t rs1 = operands[0].get(); + const int32_t rs2 = operands[1].get(); int64_t out = static_cast(static_cast(rs1 - rs2)); results[0] = RegisterValue(out, 8); break; @@ -369,50 +369,50 @@ void Instruction::execute() { break; } case Opcode::RISCV_XOR: { // XOR rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); uint64_t out = static_cast(rs1 ^ rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 ^ sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_OR: { // OR rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); uint64_t out = static_cast(rs1 | rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 | sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AND: { // AND rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); uint64_t out = static_cast(rs1 & rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t sourceImm = imm; uint64_t out = static_cast(rs1 & sourceImm); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_SLT: { // SLT rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -421,8 +421,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTU: { // SLTU rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs1 < rs2) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -431,7 +431,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); const int64_t sourceImm = imm; if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); @@ -441,7 +441,7 @@ void Instruction::execute() { break; } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); const uint64_t sourceImm = static_cast(imm); if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); @@ -451,8 +451,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BEQ: { // BEQ rs1,rs2,imm - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs1 == rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -463,8 +463,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BNE: { // BNE rs1,rs2,imm - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs1 != rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -476,8 +476,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLT: { // BLT rs1,rs2,imm - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -488,8 +488,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BLTU: { // BLTU rs1,rs2,imm - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs1 < rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -500,8 +500,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGE: { // BGE rs1,rs2,imm - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -512,8 +512,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_BGEU: { // BGEU rs1,rs2,imm - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs1 >= rs2) { branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 branchTaken_ = true; @@ -531,7 +531,7 @@ void Instruction::execute() { } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm branchAddress_ = - (srcRegVals[0].get() + imm) & ~1; // Set LSB of result to 0 + (operands[0].get() + imm) & ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; @@ -593,7 +593,7 @@ void Instruction::execute() { // if not raise address-misaligned/access-fault exception // TODO use aq and rl bits to prevent reordering with other memory // operations - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; results[0] = RegisterValue(static_cast(0), 8); break; } @@ -607,7 +607,7 @@ void Instruction::execute() { // TODO raise address misaligned or access-fault errors // TODO account for AQ and RL bits int64_t rd = signExtendW(memoryData[0].get()); - int32_t rs2 = srcRegVals[0].get(); + int32_t rs2 = operands[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -617,7 +617,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOSWAP_D_RL: case Opcode::RISCV_AMOSWAP_D_AQ_RL: { uint64_t rd = memoryData[0].get(); - uint64_t rs2 = srcRegVals[0].get(); + uint64_t rs2 = operands[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = rs2; break; @@ -628,7 +628,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd + srcRegVals[0].get()); + memoryData[0] = static_cast(rd + operands[0].get()); break; } case Opcode::RISCV_AMOADD_D: // AMOADD.D rd,rs1,rs2 @@ -637,7 +637,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOADD_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd + srcRegVals[0].get()); + memoryData[0] = static_cast(rd + operands[0].get()); break; } case Opcode::RISCV_AMOAND_W: // AMOAND.W rd,rs1,rs2 @@ -646,7 +646,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd & srcRegVals[0].get()); + memoryData[0] = static_cast(rd & operands[0].get()); break; } case Opcode::RISCV_AMOAND_D: // AMOAND.D rd,rs1,rs2 @@ -655,7 +655,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOAND_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd & srcRegVals[0].get()); + memoryData[0] = static_cast(rd & operands[0].get()); break; } case Opcode::RISCV_AMOOR_W: // AMOOR.W rd,rs1,rs2 @@ -664,7 +664,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd | srcRegVals[0].get()); + memoryData[0] = static_cast(rd | operands[0].get()); break; } case Opcode::RISCV_AMOOR_D: // AMOOR.D rd,rs1,rs2 @@ -673,7 +673,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd | srcRegVals[0].get()); + memoryData[0] = static_cast(rd | operands[0].get()); break; } case Opcode::RISCV_AMOXOR_W: // AMOXOR.W rd,rs1,rs2 @@ -682,7 +682,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_W_AQ_RL: { int64_t rd = signExtendW(memoryData[0].get()); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd ^ srcRegVals[0].get()); + memoryData[0] = static_cast(rd ^ operands[0].get()); break; } case Opcode::RISCV_AMOXOR_D: // AMOXOR.D rd,rs1,rs2 @@ -691,7 +691,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOXOR_D_AQ_RL: { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); - memoryData[0] = static_cast(rd ^ srcRegVals[0].get()); + memoryData[0] = static_cast(rd ^ operands[0].get()); break; } @@ -701,7 +701,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOMIN_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); memoryData[0] = - std::min(memoryData[0].get(), srcRegVals[0].get()); + std::min(memoryData[0].get(), operands[0].get()); break; } case Opcode::RISCV_AMOMIN_D: // AMOMIN.D rd,rs1,rs2 @@ -711,7 +711,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::min(rd, srcRegVals[0].get())); + static_cast(std::min(rd, operands[0].get())); break; } case Opcode::RISCV_AMOMINU_W: // AMOMINU.W rd,rs1,rs2 @@ -719,8 +719,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMINU_W_RL: case Opcode::RISCV_AMOMINU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = std::min(memoryData[0].get(), - srcRegVals[0].get()); + memoryData[0] = + std::min(memoryData[0].get(), operands[0].get()); break; } case Opcode::RISCV_AMOMINU_D: // AMOMINU.D rd,rs1,rs2 @@ -730,7 +730,7 @@ void Instruction::execute() { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::min(rd, srcRegVals[0].get())); + static_cast(std::min(rd, operands[0].get())); break; } @@ -740,7 +740,7 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAX_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); memoryData[0] = - std::max(memoryData[0].get(), srcRegVals[0].get()); + std::max(memoryData[0].get(), operands[0].get()); break; } case Opcode::RISCV_AMOMAX_D: // AMOMAX.D rd,rs1,rs2 @@ -750,7 +750,7 @@ void Instruction::execute() { int64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::max(rd, srcRegVals[0].get())); + static_cast(std::max(rd, operands[0].get())); break; } case Opcode::RISCV_AMOMAXU_W: // AMOMAXU.W rd,rs1,rs2 @@ -758,8 +758,8 @@ void Instruction::execute() { case Opcode::RISCV_AMOMAXU_W_RL: case Opcode::RISCV_AMOMAXU_W_AQ_RL: { results[0] = RegisterValue(signExtendW(memoryData[0].get()), 8); - memoryData[0] = std::max(memoryData[0].get(), - srcRegVals[0].get()); + memoryData[0] = + std::max(memoryData[0].get(), operands[0].get()); break; } case Opcode::RISCV_AMOMAXU_D: // AMOMAXU.D rd,rs1,rs2 @@ -769,14 +769,14 @@ void Instruction::execute() { uint64_t rd = memoryData[0].get(); results[0] = RegisterValue(rd, 8); memoryData[0] = - static_cast(std::max(rd, srcRegVals[0].get())); + static_cast(std::max(rd, operands[0].get())); break; } // Integer multiplication division extension (M) case Opcode::RISCV_MUL: { // MUL rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); results[0] = RegisterValue(static_cast(rs1 * rs2), 8); break; } @@ -789,8 +789,8 @@ void Instruction::execute() { // break; // } case Opcode::RISCV_MULHU: { // MULHU rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); results[0] = RegisterValue(mulhiuu(rs1, rs2), 8); break; } @@ -803,15 +803,15 @@ void Instruction::execute() { // break; // } case Opcode::RISCV_MULW: { // MULW rd,rs1,rs2 - const uint32_t rs1 = srcRegVals[0].get(); - const uint32_t rs2 = srcRegVals[1].get(); + const uint32_t rs1 = operands[0].get(); + const uint32_t rs2 = operands[1].get(); results[0] = RegisterValue(signExtendW(rs1 * rs2), 8); break; } case Opcode::RISCV_DIV: { // DIV rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -824,8 +824,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVW: { // DIVW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); - const int32_t rs2 = srcRegVals[1].get(); + const int32_t rs1 = operands[0].get(); + const int32_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -839,8 +839,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVU: { // DIVU rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -850,8 +850,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_DIVUW: { // DIVUW rd,rs1,rs2 - const uint32_t rs1 = srcRegVals[0].get(); - const uint32_t rs2 = srcRegVals[1].get(); + const uint32_t rs1 = operands[0].get(); + const uint32_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(-1), 8); @@ -862,8 +862,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REM: { // REM rd,rs1,rs2 - const int64_t rs1 = srcRegVals[0].get(); - const int64_t rs2 = srcRegVals[1].get(); + const int64_t rs1 = operands[0].get(); + const int64_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(rs1), 8); @@ -876,8 +876,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMW: { // REMW rd,rs1,rs2 - const int32_t rs1 = srcRegVals[0].get(); - const int32_t rs2 = srcRegVals[1].get(); + const int32_t rs1 = operands[0].get(); + const int32_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -891,8 +891,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMU: { // REMU rd,rs1,rs2 - const uint64_t rs1 = srcRegVals[0].get(); - const uint64_t rs2 = srcRegVals[1].get(); + const uint64_t rs1 = operands[0].get(); + const uint64_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(rs1, 8); @@ -902,8 +902,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_REMUW: { // REMUW rd,rs1,rs2 - const uint32_t rs1 = srcRegVals[0].get(); - const uint32_t rs2 = srcRegVals[1].get(); + const uint32_t rs1 = operands[0].get(); + const uint32_t rs2 = operands[1].get(); if (rs2 == 0) { // divide by zero results[0] = RegisterValue(static_cast(signExtendW(rs1)), 8); @@ -959,11 +959,11 @@ void Instruction::execute() { // Single-Precision Floating-Point (F) // Double-Precision Floating-Point (D) case Opcode::RISCV_FSD: { // FSD rs1,rs2,imm - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::RISCV_FSW: { // FSW rs1,rs2,imm - memoryData[0] = srcRegVals[0]; + memoryData[0] = operands[0]; break; } case Opcode::RISCV_FLD: { // FLD rd,rs1,imm @@ -979,8 +979,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_D: { // FADD.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 + rs2, 8); }); @@ -989,8 +989,8 @@ void Instruction::execute() { case Opcode::RISCV_FADD_S: { // FADD.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(rs1 + rs2), 8); }); @@ -999,8 +999,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_D: { // FSUB.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 - rs2, 8); }); @@ -1010,8 +1010,8 @@ void Instruction::execute() { case Opcode::RISCV_FSUB_S: { // FSUB.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(rs1 - rs2), 8); }); @@ -1021,8 +1021,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_D: { // FDIV.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 / rs2, 8); }); @@ -1032,8 +1032,8 @@ void Instruction::execute() { case Opcode::RISCV_FDIV_S: { // FDIV.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(rs1 / rs2), 8); }); @@ -1043,8 +1043,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_D: { // FMUL.D rd,rs1,rs2 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(rs1 * rs2, 8); }); @@ -1054,8 +1054,8 @@ void Instruction::execute() { case Opcode::RISCV_FMUL_S: { // FMUL.S rd,rs1,rs2 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(rs1 * rs2), 8); }); @@ -1065,7 +1065,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_D: { // FSQRT.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); const double sqrtAns = sqrt(rs1); @@ -1081,7 +1081,7 @@ void Instruction::execute() { case Opcode::RISCV_FSQRT_S: { // FSQRT.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); const float sqrtAns = sqrtf(rs1); @@ -1096,8 +1096,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMIN_D: { // FMIN.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); // cpp fmin reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1112,8 +1112,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMIN_S: { // FMIN.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); // Comments regarding fminf similar to RISCV_FMIN_D if (rs1 == 0 && rs2 == 0) { @@ -1126,8 +1126,8 @@ void Instruction::execute() { } case Opcode::RISCV_FMAX_D: { // FMAX.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); // cpp fmax reference: This function is not required to be sensitive to // the sign of zero, although some implementations additionally enforce @@ -1141,8 +1141,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FMAX_S: { // FMAX.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); // Comments regarding fmaxf similar to RISCV_FMAX_D if (rs1 == 0 && rs2 == 0) { @@ -1162,9 +1162,9 @@ void Instruction::execute() { // the addend is a quiet NaN. setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); - const double rs3 = srcRegVals[2].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); results[0] = RegisterValue(fma(rs1, rs2, rs3), 8); }); @@ -1174,9 +1174,9 @@ void Instruction::execute() { case Opcode::RISCV_FMADD_S: { // FMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); - const float rs3 = checkNanBox(srcRegVals[2]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); + const float rs3 = checkNanBox(operands[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1190,9 +1190,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_D: { // FNMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); - const double rs3 = srcRegVals[2].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); results[0] = RegisterValue(-(rs1 * rs2) + rs3, 8); }); @@ -1202,9 +1202,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMSUB_S: { // FNMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); - const float rs3 = checkNanBox(srcRegVals[2]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); + const float rs3 = checkNanBox(operands[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1218,9 +1218,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_D: { // FMSUB.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); - const double rs3 = srcRegVals[2].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); results[0] = RegisterValue((rs1 * rs2) - rs3, 8); }); @@ -1230,9 +1230,9 @@ void Instruction::execute() { case Opcode::RISCV_FMSUB_S: { // FMSUB.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); - const float rs3 = checkNanBox(srcRegVals[2]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); + const float rs3 = checkNanBox(operands[2]); if (std::isnan(rs1) || std::isnan(rs2) || std::isnan(rs3)) { results[0] = RegisterValue(NanBoxFloat(std::nanf("")), 8); @@ -1246,9 +1246,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_D: { // FNMADD.D rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); - const double rs3 = srcRegVals[2].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); + const double rs3 = operands[2].get(); results[0] = RegisterValue(-(rs1 * rs2) - rs3, 8); }); @@ -1258,9 +1258,9 @@ void Instruction::execute() { case Opcode::RISCV_FNMADD_S: { // FNMADD.S rd,rs1,rs2,rs3 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); - const float rs3 = checkNanBox(srcRegVals[2]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); + const float rs3 = checkNanBox(operands[2]); // Some implementations return -NaN if certain inputs are NaN but spec // requires +NaN. Ensure this happens @@ -1276,7 +1276,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_L: { // FCVT.D.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1286,7 +1286,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_W: { // FCVT.D.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1296,7 +1296,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_L: { // FCVT.S.L rd,rs1 setStaticRoundingModeThen([&] { - const int64_t rs1 = srcRegVals[0].get(); + const int64_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1306,7 +1306,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_W: { // FCVT.S.W rd,rs1 setStaticRoundingModeThen([&] { - const int32_t rs1 = srcRegVals[0].get(); + const int32_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1316,7 +1316,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_D: { // FCVT.W.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1330,7 +1330,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_W_S: { // FCVT.W.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFF, 8); @@ -1344,7 +1344,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_D: { // FCVT.L.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1358,7 +1358,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_L_S: { // FCVT.L.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); if (std::isnan(rs1)) { results[0] = RegisterValue(0x7FFFFFFFFFFFFFFF, 8); @@ -1372,7 +1372,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_D: { // FCVT.WU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1391,7 +1391,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_WU_S: { // FCVT.WU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); if (std::isnan(rs1) || rs1 >= pow(2, 32) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1410,7 +1410,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_D: { // FCVT.LU.D rd,rs1 setStaticRoundingModeThen([&] { - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1429,7 +1429,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_LU_S: { // FCVT.LU.S rd,rs1 setStaticRoundingModeThen([&] { - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); if (std::isnan(rs1) || rs1 >= pow(2, 64) - 1) { results[0] = RegisterValue(0xFFFFFFFFFFFFFFFF, 8); @@ -1448,7 +1448,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_LU: { // FCVT.D.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1458,7 +1458,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_D_WU: { // FCVT.D.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs1 = operands[0].get(); results[0] = RegisterValue((double)rs1, 8); }); @@ -1468,7 +1468,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_LU: { // FCVT.S.LU rd,rs1 setStaticRoundingModeThen([&] { - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1478,7 +1478,7 @@ void Instruction::execute() { case Opcode::RISCV_FCVT_S_WU: { // FCVT.S.WU rd,rs1 setStaticRoundingModeThen([&] { - const uint32_t rs1 = srcRegVals[0].get(); + const uint32_t rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); }); @@ -1487,50 +1487,50 @@ void Instruction::execute() { } case Opcode::RISCV_FCVT_D_S: { // FCVT.D.S rd,rs1 - const float rs1 = checkNanBox(srcRegVals[0]); + const float rs1 = checkNanBox(operands[0]); results[0] = RegisterValue((double)rs1, 8); break; } case Opcode::RISCV_FCVT_S_D: { // FCVT.S.D rd,rs1 - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat((float)rs1), 8); break; } case Opcode::RISCV_FSGNJ_D: { // FSGNJ.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(std::copysign(rs1, rs2), 8); break; } case Opcode::RISCV_FSGNJ_S: { // FSGNJ.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, rs2)), 8); break; } case Opcode::RISCV_FSGNJN_D: { // FSGNJN.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); results[0] = RegisterValue(std::copysign(rs1, -rs2), 8); break; } case Opcode::RISCV_FSGNJN_S: { // FSGNJN.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); results[0] = RegisterValue(NanBoxFloat(std::copysign(rs1, -rs2)), 8); break; } case Opcode::RISCV_FSGNJX_D: { // FSGNJX.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); const double xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1538,8 +1538,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FSGNJX_S: { // FSGNJX.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); const float xorSign = pow(-1, std::signbit(rs1) ^ std::signbit(rs2)); @@ -1548,25 +1548,25 @@ void Instruction::execute() { } case Opcode::RISCV_FMV_D_X: { // FMV.D.X rd,rs1 - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_X_D: { // FMV.X.D rd,rs1 - const double rs1 = srcRegVals[0].get(); + const double rs1 = operands[0].get(); results[0] = RegisterValue(rs1, 8); break; } case Opcode::RISCV_FMV_W_X: { // FMV.W.X rd,rs1 - const float rs1 = srcRegVals[0].get(); + const float rs1 = operands[0].get(); results[0] = RegisterValue(NanBoxFloat(rs1), 8); break; } case Opcode::RISCV_FMV_X_W: { // FMV.X.W rd,rs1 - const uint64_t rs1 = srcRegVals[0].get(); + const uint64_t rs1 = operands[0].get(); results[0] = RegisterValue(signExtendW(rs1), 8); break; @@ -1585,8 +1585,8 @@ void Instruction::execute() { // either input is a signaling NaN. Qemu doesn't seem to set CSR flags // with sNANs so unsure of correct implementation. Also require proper // Zicsr implementation - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1596,8 +1596,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FEQ_S: { // FEQ.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); if (rs1 == rs2 && !std::isnan(rs1) && !std::isnan(rs2)) { results[0] = RegisterValue(static_cast(1), 8); @@ -1607,8 +1607,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_D: { // FLT.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1621,8 +1621,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLT_S: { // FLT.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1635,8 +1635,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_D: { // FLE.D rd,rs1,rs2 - const double rs1 = srcRegVals[0].get(); - const double rs2 = srcRegVals[1].get(); + const double rs1 = operands[0].get(); + const double rs2 = operands[1].get(); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete @@ -1649,8 +1649,8 @@ void Instruction::execute() { break; } case Opcode::RISCV_FLE_S: { // FLE.S rd,rs1,rs2 - const float rs1 = checkNanBox(srcRegVals[0]); - const float rs2 = checkNanBox(srcRegVals[1]); + const float rs1 = checkNanBox(operands[0]); + const float rs2 = checkNanBox(operands[1]); if (std::isnan(rs1) || std::isnan(rs2)) { // TODO: set csr flag when Zicsr implementation is complete From 60bcfb9819a92c530a00f24ee86e710868794be9 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 11:28:58 +0000 Subject: [PATCH 057/115] Undo operands renaming in docs --- .../developer/arch/supported/aarch64.rst | 22 +++++++++---------- .../sphinx/developer/arch/supported/riscv.rst | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 6673d884f1..14426ef90c 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -122,17 +122,17 @@ The first step to add a new instruction (and the only, for many instructions) is There are several useful variables that execution behaviours have access to: -``srcRegVals`` +``operands`` .. _aarch64-adding-execution-behaviour-operands: - This is a vector of ``RegisterValue``, with each value corresponding to one of the input operands. For most instructions, ``srcRegVals[0]`` will be the *second* operand as written textually, as the first operand is typically the destination register. E.g., for the instruction ``add w0, w1, w2``, ``srcRegVals[0]`` will correspond to ``w1`` and ``[1]`` to ``w2``. + This is a vector of ``RegisterValue``, with each value corresponding to one of the input operands. For most instructions, ``operands[0]`` will be the *second* operand as written textually, as the first operand is typically the destination register. E.g., for the instruction ``add w0, w1, w2``, ``operands[0]`` will correspond to ``w1`` and ``[1]`` to ``w2``. - Some instructions have "implicit" register reads: these are added to the **start** of the operand array. E.g., the instruction ``b.ne #16`` implicitly reads the "NZCV" flags. In this case, ``srcRegVals[0]`` will be the value of the flag register. + Some instructions have "implicit" register reads: these are added to the **start** of the operand array. E.g., the instruction ``b.ne #16`` implicitly reads the "NZCV" flags. In this case, ``operands[0]`` will be the value of the flag register. - Some instructions have operands to which they both read and write, such as ``fmla v0.d, v1.d, v2.d`` both writing to *and* reading from ``v0.d``; in this case, ``srcRegVals[0]`` is ``v0.d``, and ``[1]`` and ``[2]`` are ``v1.d`` and ``v2.d`` respectively. + Some instructions have operands to which they both read and write, such as ``fmla v0.d, v1.d, v2.d`` both writing to *and* reading from ``v0.d``; in this case, ``operands[0]`` is ``v0.d``, and ``[1]`` and ``[2]`` are ``v1.d`` and ``v2.d`` respectively. - Instructions such as stores may not have any destination registers at all. In these cases, the ``srcRegVals`` indices match the positions as they appear: the first operand is ``[0]``, the second ``[1]``, and so on. + Instructions such as stores may not have any destination registers at all. In these cases, the ``operands`` indices match the positions as they appear: the first operand is ``[0]``, the second ``[1]``, and so on. ``results`` This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register. @@ -142,7 +142,7 @@ There are several useful variables that execution behaviours have access to: Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``. ``metadata`` - Each instruction stores a simplified form of the full disassembly metadata generated by Capstone. This is stored in the ``metadata`` member variable, and is of type ``InstructionMetadata``. The metadata object contains an ``metadata.operands`` array with entries corresponding to the textual operands of the instruction. **Note:** Unlike the instruction's ``srcRegVals`` member variable, ``metadata.operands`` entries correspond directly to their textual equivalent. For example, in the instruction ``add w0, w1, w2``, ``metadata.operands[0]`` will describe ``w0``, ``[1]`` describes ``w1``, and so on. + Each instruction stores a simplified form of the full disassembly metadata generated by Capstone. This is stored in the ``metadata`` member variable, and is of type ``InstructionMetadata``. The metadata object contains an ``metadata.operands`` array with entries corresponding to the textual operands of the instruction. **Note:** Unlike the instruction's ``operands`` member variable, ``metadata.operands`` entries correspond directly to their textual equivalent. For example, in the instruction ``add w0, w1, w2``, ``metadata.operands[0]`` will describe ``w0``, ``[1]`` describes ``w1``, and so on. The primary use for this data is to retrieve immediate values. For example, with the instruction ``add w0, w1, #1``, ``metadata.operands[2].imm`` would contain the value ``1``. Floating point immediates are similarly available, using ``.fp`` in place of ``.imm``. @@ -154,11 +154,11 @@ SimEng supports the Arm SVE extension and thus the use of ``Z`` vector registers Scalable Matrix Extension '''''''''''''''''''''''''' -Also supported is the Arm SME extension and thus the use of ``ZA`` sub-tile registers. The implementation of the ``ZA`` register is to treat each horizontal row the same as a vector register. Therefore, if a source operand is a sub-tile of ``ZA`` and contains 16 rows, then there will be 16 corresponding entries in the ``srcRegVals`` vector. Likewise, if a destination operand is ``ZA`` or a sub-tile of ``ZA`` then the ``results`` vector will require the corresponding number of horizontal rows. +Also supported is the Arm SME extension and thus the use of ``ZA`` sub-tile registers. The implementation of the ``ZA`` register is to treat each horizontal row the same as a vector register. Therefore, if a source operand is a sub-tile of ``ZA`` and contains 16 rows, then there will be 16 corresponding entries in the ``operands`` vector. Likewise, if a destination operand is ``ZA`` or a sub-tile of ``ZA`` then the ``results`` vector will require the corresponding number of horizontal rows. -SME instructions can also operate on sub-tile slices; individual rows or columns within a sub-tile. Regardless of whether a whole sub-tile or a slice is used as a source operand, all rows associated with said tile will be added to the ``srcRegVals`` vector. There are two reasons for this. First, the index value pointing to the relevant slice cannot be evaluated before instruction execution, thus, all sub-tile rows need to be provided. Second, if the source slice is a vertical slice (or a column of the sub-tile) then an element from each row is needed to construct the correct output. +SME instructions can also operate on sub-tile slices; individual rows or columns within a sub-tile. Regardless of whether a whole sub-tile or a slice is used as a source operand, all rows associated with said tile will be added to the ``operands`` vector. There are two reasons for this. First, the index value pointing to the relevant slice cannot be evaluated before instruction execution, thus, all sub-tile rows need to be provided. Second, if the source slice is a vertical slice (or a column of the sub-tile) then an element from each row is needed to construct the correct output. -Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``srcRegVals`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. +Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``operands`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. Before implementing any further SME functionality we highly recommend familiarising yourself with the specification; found `here `_. @@ -202,7 +202,7 @@ Capstone provides a ``cstool`` utility, which provides a visual representation o Zero registers ************** -AArch64 provides two zero registers, ``WZR`` and ``XZR``, which are always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``srcRegVals`` entry with a 0-value ``RegisterValue``. +AArch64 provides two zero registers, ``WZR`` and ``XZR``, which are always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``operands`` entry with a 0-value ``RegisterValue``. For instructions that are capable of generating multiple results (typically flag-setting instructions), they can claim to write to one of the zero registers: in these cases, the result is discarded. This implementation supports this behaviour, and reduces the number of available ``results`` entries accordingly. @@ -211,7 +211,7 @@ Loads and stores In addition to an execution behaviour, memory instructions also require a new entry in the address generation behaviour table found in ``src/lib/arch/aarch64/Instruction_address.cc``. These entries are responsible for describing the method used to generate the addresses that these instructions will read from or write to. -Address generation is expected to generate one or more instances of ``MemoryAccessTarget``, containing an address and the number of bytes to access. The same variables described above (``srcRegVals``, ``metadata``) are available to use to generate these addresses. +Address generation is expected to generate one or more instances of ``MemoryAccessTarget``, containing an address and the number of bytes to access. The same variables described above (``operands``, ``metadata``) are available to use to generate these addresses. Once the addresses have been generated, they should be supplied in a vector to the ``setMemoryAddresses`` helper function. diff --git a/docs/sphinx/developer/arch/supported/riscv.rst b/docs/sphinx/developer/arch/supported/riscv.rst index aa07245574..7049093d68 100644 --- a/docs/sphinx/developer/arch/supported/riscv.rst +++ b/docs/sphinx/developer/arch/supported/riscv.rst @@ -60,7 +60,7 @@ The process for adding a new instruction is very similar to that of :ref:`AArch6 Zero registers ************** -RISC-V provides a zero register ``RO`` which is always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``srcRegVals`` entry with a 0-value ``RegisterValue``. +RISC-V provides a zero register ``RO`` which is always read as 0. This implementation mirrors that behaviour, and will automatically populate the relevant ``operands`` entry with a 0-value ``RegisterValue``. For instructions that write to the zero registers, the result is discarded. The number of available ``results`` entries is reduced accordingly. @@ -69,7 +69,7 @@ Loads and stores In addition to an execution behaviour, memory instructions also require a new entry in the address generation behaviour table found in ``src/lib/arch/riscv/Instruction_address.cc``. These entries are responsible for describing the method used to generate the addresses that these instructions will read from or write to. -Address generation is expected to generate one or more instances of ``MemoryAddressTarget``, containing an address and the number of bytes to access. The same variables as described in the :ref:`AArch64 documentation ` (``srcRegVals``, ``metadata``) are available to use to generate these addresses. +Address generation is expected to generate one or more instances of ``MemoryAddressTarget``, containing an address and the number of bytes to access. The same variables as described in the :ref:`AArch64 documentation ` (``operands``, ``metadata``) are available to use to generate these addresses. Once the addresses have been generated, they should be supplied in a vector to the ``setMemoryAddresses`` helper function. From cac171510a16d201bed1c55fc44d9de097318cc2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 11:32:05 +0000 Subject: [PATCH 058/115] Undo operandsPending rename --- .../simeng/arch/aarch64/Instruction.hh | 2 +- src/lib/arch/aarch64/Instruction.cc | 4 ++-- src/lib/arch/aarch64/Instruction_decode.cc | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 79d1115dbf..3636e681cd 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -416,7 +416,7 @@ class Instruction : public simeng::Instruction { // Scheduling /** The number of source operands that have not yet had values supplied. Used * to determine execution readiness. */ - uint16_t numSrcOpsPending = 0; + short operandsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index a8fbf6706c..a3e0e698ad 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -66,7 +66,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { "Attempted to provide an uninitialised RegisterValue"); operands[i] = value; - numSrcOpsPending--; + operandsPending--; } void Instruction::supplyData(uint64_t address, const RegisterValue& data) { @@ -92,7 +92,7 @@ span Instruction::getData() const { return {memoryData.data(), memoryData.size()}; } -bool Instruction::canExecute() const { return (numSrcOpsPending == 0); } +bool Instruction::canExecute() const { return (operandsPending == 0); } const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 0cf8b02c59..4e60ae1b62 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -196,7 +196,7 @@ void Instruction::decode() { for (size_t i = 0; i < metadata.implicitSourceCount; i++) { sourceRegisters.push_back( csRegToRegister(static_cast(metadata.implicitSources[i]))); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; } @@ -239,7 +239,7 @@ void Instruction::decode() { // unaltered row values sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - numSrcOpsPending++; + operandsPending++; } } else { // Add register writes to destinations, but skip zero-register @@ -257,12 +257,12 @@ void Instruction::decode() { for (int i = 0; i < regs.size(); i++) { sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - numSrcOpsPending++; + operandsPending++; } } else { // Add register reads to destinations sourceRegisters.push_back(csRegToRegister(op.reg)); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; } if (op.shift.value > 0) isNoShift_ = false; // Identify shift operands @@ -270,7 +270,7 @@ void Instruction::decode() { } else if (op.type == ARM64_OP_MEM) { // Memory operand accessesMemory = true; sourceRegisters.push_back(csRegToRegister(op.mem.base)); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; if (metadata.writeback) { @@ -281,7 +281,7 @@ void Instruction::decode() { if (op.mem.index) { // Register offset; add to sources sourceRegisters.push_back(csRegToRegister(op.mem.index)); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; } } else if (op.type == ARM64_OP_SME_INDEX) { // SME instruction with index @@ -298,7 +298,7 @@ void Instruction::decode() { for (int i = 0; i < regs.size(); i++) { sourceRegisters.push_back(regs[i]); sourceRegisterCount++; - numSrcOpsPending++; + operandsPending++; if (op.access & cs_ac_type::CS_AC_WRITE) { destinationRegisters.push_back(regs[i]); destinationRegisterCount++; @@ -313,13 +313,13 @@ void Instruction::decode() { destinationRegisterCount++; } else if (op.access & cs_ac_type::CS_AC_READ) { sourceRegisters.push_back(csRegToRegister(op.sme_index.reg)); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; } } // Register that is base of index will always be a source operand sourceRegisters.push_back(csRegToRegister(op.sme_index.base)); - numSrcOpsPending++; + operandsPending++; sourceRegisterCount++; } else if (op.type == ARM64_OP_REG_MRS) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); @@ -333,7 +333,7 @@ void Instruction::decode() { sourceRegisters.push_back( {RegisterType::SYSTEM, static_cast(sysRegTag)}); sourceRegisterCount++; - numSrcOpsPending++; + operandsPending++; } } else if (op.type == ARM64_OP_REG_MSR) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); @@ -646,7 +646,7 @@ void Instruction::decode() { for (uint16_t i = 0; i < sourceRegisterCount; i++) { if (sourceRegisters[i] == Instruction::ZERO_REGISTER) { operands[i] = RegisterValue(0, 8); - numSrcOpsPending--; + operandsPending--; } } } From 23b8f254caa98aa90829f611e7eddceb8a974648 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 11:33:53 +0000 Subject: [PATCH 059/115] Undo RISC-V operandsPending rename --- src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/riscv/Instruction.cc | 4 ++-- src/lib/arch/riscv/Instruction_decode.cc | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 8c44af6c9c..4bd1f6768f 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -218,7 +218,7 @@ class Instruction : public simeng::Instruction { // Scheduling /** The number of source operands that have not yet had values supplied. Used * to determine execution readiness. */ - uint16_t numSrcOpsPending = 0; + short operandsPending = 0; // Execution /** Generate an ExecutionNotYetImplemented exception. */ diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index df06acaaa9..1af879f577 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -62,7 +62,7 @@ void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) { "Attempted to provide an uninitialised RegisterValue"); operands[i] = value; - numSrcOpsPending--; + operandsPending--; } void Instruction::supplyData(uint64_t address, const RegisterValue& data) { @@ -88,7 +88,7 @@ span Instruction::getData() const { return {memoryData.data(), memoryData.size()}; } -bool Instruction::canExecute() const { return (numSrcOpsPending == 0); } +bool Instruction::canExecute() const { return (operandsPending == 0); } const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index cb48916891..6ca1ce5925 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -152,7 +152,7 @@ void Instruction::decode() { // Catch zero register references and pre-complete those operands operands[sourceRegisterCount] = RegisterValue(0, 8); } else { - numSrcOpsPending++; + operandsPending++; } sourceRegisterCount++; @@ -194,7 +194,7 @@ void Instruction::decode() { // Catch zero register references and pre-complete those operands operands[sourceRegisterCount] = RegisterValue(0, 8); } else { - numSrcOpsPending++; + operandsPending++; } sourceRegisterCount++; @@ -207,7 +207,7 @@ void Instruction::decode() { sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); imm = op.mem.disp; sourceRegisterCount++; - numSrcOpsPending++; + operandsPending++; } // First operands never immediate From 267b1d3cd059224d6cd187b78d3b61627b6b3488 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 12:54:23 +0000 Subject: [PATCH 060/115] Undo getInitialStackPointer rename --- src/include/simeng/kernel/Linux.hh | 2 +- src/include/simeng/kernel/LinuxProcess.hh | 2 +- src/lib/arch/aarch64/Architecture.cc | 2 +- src/lib/arch/riscv/Architecture.cc | 2 +- src/lib/kernel/Linux.cc | 17 +- src/lib/kernel/LinuxProcess.cc | 2 +- test/regression/RegressionTest.cc | 2 +- test/regression/aarch64/MicroOperation.cc | 184 +++++++------- test/regression/aarch64/SmokeTest.cc | 4 +- .../aarch64/instructions/comparison.cc | 4 +- test/regression/aarch64/instructions/load.cc | 12 +- test/regression/aarch64/instructions/sme.cc | 8 +- test/regression/aarch64/instructions/store.cc | 230 +++++++++--------- test/regression/aarch64/instructions/sve.cc | 55 ++--- .../riscv/instructions/compressed.cc | 20 +- test/regression/riscv/instructions/store.cc | 4 +- 16 files changed, 271 insertions(+), 279 deletions(-) diff --git a/src/include/simeng/kernel/Linux.hh b/src/include/simeng/kernel/Linux.hh index 0908d59006..9e859547aa 100644 --- a/src/include/simeng/kernel/Linux.hh +++ b/src/include/simeng/kernel/Linux.hh @@ -134,7 +134,7 @@ class Linux { void createProcess(const LinuxProcess& process); /** Retrieve the initial stack pointer. */ - uint64_t getInitialStackPointer() const; + uint64_t getStackPointer() const; /** brk syscall: change data segment size. Sets the program break to * `addr` if reasonable, and returns the program break. */ diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index c1f1ca9d81..cda3de8c0d 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -95,7 +95,7 @@ class LinuxProcess { uint64_t getEntryPoint() const; /** Get the initial stack pointer address. */ - uint64_t getInitialStackPointer() const; + uint64_t getStackPointer() const; /** Get the path of the executable. */ std::string getPath() const; diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 5fa77159b4..2b08b1b44c 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -245,7 +245,7 @@ ProcessStateChange Architecture::getInitialState() const { // Set ProcessStateChange type changes.type = ChangeType::REPLACEMENT; - uint64_t stackPointer = linux_.getInitialStackPointer(); + uint64_t stackPointer = linux_.getStackPointer(); // Set the stack pointer register changes.modifiedRegisters.push_back({RegisterType::GENERAL, 31}); changes.modifiedRegisterValues.push_back(stackPointer); diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 344ef8c0e7..11338bfdb8 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -274,7 +274,7 @@ ProcessStateChange Architecture::getInitialState() const { // Set ProcessStateChange type changes.type = ChangeType::REPLACEMENT; - uint64_t stackPointer = linux_.getInitialStackPointer(); + uint64_t stackPointer = linux_.getStackPointer(); // Set the stack pointer register changes.modifiedRegisters.push_back({RegisterType::GENERAL, 2}); changes.modifiedRegisterValues.push_back(stackPointer); diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index 10940336f1..d8e1a01845 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -23,14 +23,13 @@ namespace kernel { void Linux::createProcess(const LinuxProcess& process) { assert(process.isValid() && "Attempted to use an invalid process"); assert(processStates_.size() == 0 && "Multiple processes not yet supported"); - processStates_.push_back( - {.pid = 0, // TODO: create unique PIDs - .path = process.getPath(), - .startBrk = process.getHeapStart(), - .currentBrk = process.getHeapStart(), - .initialStackPointer = process.getInitialStackPointer(), - .mmapRegion = process.getMmapStart(), - .pageSize = process.getPageSize()}); + processStates_.push_back({.pid = 0, // TODO: create unique PIDs + .path = process.getPath(), + .startBrk = process.getHeapStart(), + .currentBrk = process.getHeapStart(), + .initialStackPointer = process.getStackPointer(), + .mmapRegion = process.getMmapStart(), + .pageSize = process.getPageSize()}); processStates_.back().fileDescriptorTable.push_back(STDIN_FILENO); processStates_.back().fileDescriptorTable.push_back(STDOUT_FILENO); processStates_.back().fileDescriptorTable.push_back(STDERR_FILENO); @@ -84,7 +83,7 @@ std::string Linux::getSpecialFile(const std::string filename) { return filename; } -uint64_t Linux::getInitialStackPointer() const { +uint64_t Linux::getStackPointer() const { assert(processStates_.size() > 0 && "Attempted to retrieve a stack pointer before creating a process"); diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index d2dcb49891..9d5b40d930 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -108,7 +108,7 @@ uint64_t LinuxProcess::getProcessImageSize() const { return size_; } uint64_t LinuxProcess::getEntryPoint() const { return entryPoint_; } -uint64_t LinuxProcess::getInitialStackPointer() const { return stackPointer_; } +uint64_t LinuxProcess::getStackPointer() const { return stackPointer_; } void LinuxProcess::createStack(char** processImage) { // Decrement the stack pointer and populate with initial stack state diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 76a933a329..37655d01e3 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -80,7 +80,7 @@ void RegressionTest::run(const char* source, const char* triple, // Populate the heap with initial data (specified by the test being run). ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), - process_->getInitialStackPointer()); + process_->getStackPointer()); std::copy(initialHeapData_.begin(), initialHeapData_.end(), processMemory_ + process_->getHeapStart()); diff --git a/test/regression/aarch64/MicroOperation.cc b/test/regression/aarch64/MicroOperation.cc index 7591e3288b..3f53286b43 100644 --- a/test/regression/aarch64/MicroOperation.cc +++ b/test/regression/aarch64/MicroOperation.cc @@ -647,21 +647,21 @@ TEST_P(MicroOp, storePairD) { stp d4, d5, [sp, #16] stp d6, d7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -3.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 3.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 5.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), -1.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), -0.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 0.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 1.5); } @@ -702,37 +702,37 @@ TEST_P(MicroOp, storePairQ) { stp q4, q5, [sp, #32] stp q6, q7, [sp, #-32]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 0xCAFEABBACAFEABBA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 0xFEDCBAFEDCBAFEDC); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 960), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 960), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 952), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 952), 0xFEDCBAFEDCBAFEDC); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 944), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 944), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 936), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 936), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 928), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 928), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 920), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 920), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 912), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 912), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 904), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 904), 0xCAFEABBACAFEABBA); } @@ -754,21 +754,21 @@ TEST_P(MicroOp, storePairS) { stp s4, s5, [sp, #8] stp s6, s7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), -3.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 5.0f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1004), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), -0.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 0.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 996), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 1.5f); } @@ -790,21 +790,21 @@ TEST_P(MicroOp, storePairW) { stp w4, w5, [sp, #8] stp w6, w7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 84); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 96); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 36); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1004), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 60); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 996), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 72); } @@ -826,21 +826,21 @@ TEST_P(MicroOp, storePairX) { stp x4, x5, [sp, #16] stp x6, x7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); } @@ -869,13 +869,13 @@ TEST_P(MicroOp, storeB) { str b2, [sp, #1] str b3, [sp, #-1]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1023), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1023), 0xFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1022), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), 0xBA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1021), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1021), 0xCA); } @@ -893,13 +893,13 @@ TEST_P(MicroOp, storeD) { str d2, [sp, #8] str d3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 1.5); } @@ -928,13 +928,13 @@ TEST_P(MicroOp, storeH) { str h2, [sp, #2] str h3, [sp, #-2]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xABBA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1022), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), 0x5678); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 0xCAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1018), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1018), 0x1234); } @@ -967,21 +967,21 @@ TEST_P(MicroOp, storeQ) { str q2, [sp, #16] str q3, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 0xABBACAFEABBACAFE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 0x1234567898765432); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 0xABCDEFABCDEFABCD); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 0xCAFEABBACAFEABBA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 0x9876543212345678); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 0xFEDCBAFEDCBAFEDC); } @@ -999,13 +999,13 @@ TEST_P(MicroOp, storeS) { str s2, [sp, #4] str s3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 3.0f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -1.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 1.5f); } @@ -1023,13 +1023,13 @@ TEST_P(MicroOp, storeW) { str w2, [sp, #4] str w3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1020), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1012), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 36); } @@ -1047,13 +1047,13 @@ TEST_P(MicroOp, storeX) { str x2, [sp, #8] str x3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); } @@ -1078,13 +1078,13 @@ TEST_P(MicroOp, storeThenLoad) { ldr x7, [sp, #8] ldr x8, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); EXPECT_EQ(getGeneralRegister(5), 12); EXPECT_EQ(getGeneralRegister(6), 24); @@ -1117,21 +1117,21 @@ TEST_P(MicroOp, storeThenLoadPair) { ldp x12, x13, [sp, #16] ldp x14, x15, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 976), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 968), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); EXPECT_EQ(getGeneralRegister(8), 12); EXPECT_EQ(getGeneralRegister(9), 24); diff --git a/test/regression/aarch64/SmokeTest.cc b/test/regression/aarch64/SmokeTest.cc index 1918929162..c9956d6825 100644 --- a/test/regression/aarch64/SmokeTest.cc +++ b/test/regression/aarch64/SmokeTest.cc @@ -34,9 +34,9 @@ TEST_P(SmokeTest, stack) { str w0, [sp, -4] str w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 7u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); } diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 1acabddfeb..6f04002bad 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -36,7 +36,7 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(0)), 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 100); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 89); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 89); // 64-bit initialHeapData_.resize(16); @@ -68,7 +68,7 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(0)), 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 101); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 76); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 76); } // Test that NZCV flags are set correctly by the 32-bit cmn instruction diff --git a/test/regression/aarch64/instructions/load.cc b/test/regression/aarch64/instructions/load.cc index 09269eebb8..cc407a4f99 100644 --- a/test/regression/aarch64/instructions/load.cc +++ b/test/regression/aarch64/instructions/load.cc @@ -605,14 +605,10 @@ TEST_P(InstLoad, ldadd) { EXPECT_EQ(getGeneralRegister(6), 48); EXPECT_EQ(getGeneralRegister(7), 128); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), - 112); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), - 64); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 960), - 176); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 928), - 128); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 112); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 64); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 960), 176); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 928), 128); } TEST_P(InstLoad, ldar) { diff --git a/test/regression/aarch64/instructions/sme.cc b/test/regression/aarch64/instructions/sme.cc index af209949b2..d553821771 100644 --- a/test/regression/aarch64/instructions/sme.cc +++ b/test/regression/aarch64/instructions/sme.cc @@ -300,7 +300,7 @@ TEST_P(InstSme, st1d) { st1d {za1h.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), src[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src[i % 2]); @@ -361,7 +361,7 @@ TEST_P(InstSme, st1d) { st1d {za1v.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), src_vert[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src_vert[i % 2]); @@ -424,7 +424,7 @@ TEST_P(InstSme, st1w) { st1w {za1h.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), src[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src[i % 4]); @@ -485,7 +485,7 @@ TEST_P(InstSme, st1w) { st1w {za1v.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), src_vert[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src_vert[i % 4]); diff --git a/test/regression/aarch64/instructions/store.cc b/test/regression/aarch64/instructions/store.cc index 6d6876b494..1cfb83173c 100644 --- a/test/regression/aarch64/instructions/store.cc +++ b/test/regression/aarch64/instructions/store.cc @@ -21,13 +21,13 @@ TEST_P(InstStore, stlr) { stlrb w3, [sp] add sp, sp, #1 )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 3), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); // stlr @@ -50,13 +50,13 @@ TEST_P(InstStore, stlr) { add sp, sp, #4 )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0xFFFFFFFFFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0xBEEF); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xBABA); } @@ -76,16 +76,16 @@ TEST_P(InstStore, strb) { mov x6, -16 strb w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 3), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 18), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 18), 0x12); } @@ -105,17 +105,17 @@ TEST_P(InstStore, strh) { mov x6, -16 strh w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 6), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 6), 0x1234); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xCD89); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0x3401); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 0x1234); } @@ -136,17 +136,17 @@ TEST_P(InstStore, strd) { mov x6, -16 str d1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 2.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), -0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 7.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); } @@ -158,16 +158,16 @@ TEST_P(InstStore, strq) { str q0, [sp], -32 str q1, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0.25); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 0.25); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 32); + process_->getStackPointer() - 32); } TEST_P(InstStore, strs) { @@ -187,16 +187,16 @@ TEST_P(InstStore, strs) { mov x6, -8 str s1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 28), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); } @@ -216,17 +216,17 @@ TEST_P(InstStore, strw) { mov x6, -16 str w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0xABABull << 16); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 0x1234ull << 16); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xCD89ull << 16); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0x3401ull << 16); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xABABull << 16); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0x1234ull << 16); } @@ -247,17 +247,17 @@ TEST_P(InstStore, strx) { mov x6, -16 str x1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 0xABABull << 32); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0x1234ull << 32); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0xCD89ull << 32); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0x3401ull << 32); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xABABull << 32); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), 0x1234ull << 32); } @@ -287,7 +287,7 @@ TEST_P(InstStore, st1_single_struct) { st1 {v0.b}[12], [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 16); + process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), static_cast(1)); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -322,7 +322,7 @@ TEST_P(InstStore, st1_single_struct) { st1 {v0.h}[7], [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 16); + process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0xab); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -355,7 +355,7 @@ TEST_P(InstStore, st1_single_struct) { st1 {v0.s}[3], [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 16); + process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0.5f); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 1); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 2); @@ -381,7 +381,7 @@ TEST_P(InstStore, st1_single_struct) { st1 {v1.d}[0], [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 16); + process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 0.5); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 1000UL); @@ -400,7 +400,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 32); + process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 16; i++) { @@ -424,7 +424,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 32); + process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 2; i++) { @@ -448,7 +448,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 32); + process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 4; i++) { @@ -474,7 +474,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 16; i++) { @@ -508,7 +508,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 2; i++) { @@ -542,7 +542,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [sp] )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 4; i++) { @@ -587,11 +587,11 @@ TEST_P(InstStore, st1fourv_post) { st1 {v4.2s, v5.2s, v6.2s, v7.2s}, [x1], x2 )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); EXPECT_EQ(getGeneralRegister(0), - process_->getInitialStackPointer() - 32); + process_->getStackPointer() - 32); EXPECT_EQ(getGeneralRegister(1), - process_->getInitialStackPointer() - 15); + process_->getStackPointer() - 15); for (int i = 0; i < 2; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -641,11 +641,11 @@ TEST_P(InstStore, st1fourv_post) { st1 {v4.4s, v5.4s, v6.4s, v7.4s}, [x1], x2 )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 128); + process_->getStackPointer() - 128); EXPECT_EQ(getGeneralRegister(0), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); EXPECT_EQ(getGeneralRegister(1), - process_->getInitialStackPointer() - 47); + process_->getStackPointer() - 47); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -687,7 +687,7 @@ TEST_P(InstStore, st2_multi_struct) { st2 {v0.4s, v1.4s}, [sp], #32 )"); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer()); + process_->getStackPointer()); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) - 32 + 8 * i), @@ -719,21 +719,21 @@ TEST_P(InstStore, stpd) { stp d3, d0, [sp, 16] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 64), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 2.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), -0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 7.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 7.5); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); } @@ -749,21 +749,21 @@ TEST_P(InstStore, stps) { stp s2, s3, [sp, 8]! stp s3, s0, [sp, 8] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 28), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 20), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 12), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); } TEST_P(InstStore, stpwi) { @@ -772,9 +772,9 @@ TEST_P(InstStore, stpwi) { movz w1, #42 stp w0, w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 7u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); } @@ -790,40 +790,40 @@ TEST_P(InstStore, stpq) { stp q2, q3, [sp, 32]! stp q3, q0, [sp, 32] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 128), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 128), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 120), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 120), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 112), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 112), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 104), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 104), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 96), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 96), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 88), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 88), -0.125f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 80), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 80), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 72), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 72), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 64), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 56), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), 7.5f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 48), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 40), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 32), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 24), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 2.f); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.f); EXPECT_EQ(getGeneralRegister(31), - process_->getInitialStackPointer() - 64); + process_->getStackPointer() - 64); } TEST_P(InstStore, stpx) { @@ -841,17 +841,17 @@ TEST_P(InstStore, stpx) { stp x2, x3, [sp] stp x4, x5, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1024), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 7u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1016), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 42u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1008), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 8u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 1000), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 43u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 992), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 9u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 984), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 44u); } @@ -860,37 +860,37 @@ TEST_P(InstStore, stur) { movz w0, #42 stur w0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); RUN_AARCH64(R"( movz x0, #42 stur x0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); RUN_AARCH64(R"( fmov s0, -0.125 stur s0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), -0.125); RUN_AARCH64(R"( fmov d0, -0.125 stur d0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); RUN_AARCH64(R"( fmov v0.2d, -0.125 stur q0, [sp, #-16] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 16), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); } @@ -901,9 +901,9 @@ TEST_P(InstStore, sturh) { movz w1, #128 sturh w1, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 2), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 42u); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 128u); } diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index 6c2e871aed..6982fb8c9e 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -6196,14 +6196,13 @@ TEST_P(InstSve, st1b) { )"); for (int i = 0; i < (VL / 8); i++) { - EXPECT_EQ( - getMemoryValue(process_->getInitialStackPointer() - 4095 + i), - src[i % 16]); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + i), + src[i % 16]); } for (int i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(4 * (VL / 16) + i), src[i % 16]); } - uint64_t base = process_->getInitialStackPointer() - 8190 + 4 * (VL / 8); + uint64_t base = process_->getStackPointer() - 8190 + 4 * (VL / 8); for (int i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(base + i), src[i % 16]); } @@ -6242,9 +6241,8 @@ TEST_P(InstSve, st1b_scatter) { )"); for (uint64_t i = 0; i < VL / 64; i++) { - EXPECT_EQ( - getMemoryValue(process_->getInitialStackPointer() - (3 * i)), - src[(8 * i) % 16]); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - (3 * i)), + src[(8 * i) % 16]); } for (uint64_t i = 0; i < VL / 128; i++) { @@ -6362,9 +6360,9 @@ TEST_P(InstSve, st1d) { )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (i * 8)), - src[i % 4]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), + src[i % 4]); } for (int i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(65792 + (i * 8)), src[i % 4]); @@ -6402,11 +6400,11 @@ TEST_P(InstSve, st2d) { )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (2 * i * 8)), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + + (2 * i * 8)), 3); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (2 * i * 8) + 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + + (2 * i * 8) + 8), 4); } @@ -6507,9 +6505,9 @@ TEST_P(InstSve, st1w) { )"); for (int i = 0; i < (VL / 32); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (i * 4)), - src[i % 4]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), + src[i % 4]); } for (int i = 0; i < (VL / 32); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (i * 4)), src[i % 4]); @@ -6583,9 +6581,9 @@ TEST_P(InstSve, st1w) { fillNeonCombined( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, {0ul}, VL / 16); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (i * 4)), - srcC[i]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), + srcC[i]); } std::array srcD = @@ -6614,9 +6612,8 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #0, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ( - getMemoryValue(process_->getInitialStackPointer() - 4095 + i), - 0xFF); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4095 + i), + 0xFF); } fillHeap(heap8, {0xDE}, VL / 64); @@ -6632,7 +6629,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #1, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - (4095 - (VL / 64)) + i), 0xDE); } @@ -6650,7 +6647,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #2, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - (4095 - (VL / 64) * 2) + i), 0x12); } @@ -6668,7 +6665,7 @@ TEST_P(InstSve, str_predicate) { str p0, [sp, #3, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - (4095 - (VL / 64) * 3) + i), 0x98); } @@ -6697,9 +6694,9 @@ TEST_P(InstSve, str_vector) { str z1, [x1, #4, mul vl] )"); for (int i = 0; i < (VL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - - 4095 + (i * 8)), - src[i % 8]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), + src[i % 8]); } for (int i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (VL / 2) + (i * 8)), diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index e15af7ffff..99823a3504 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -87,9 +87,9 @@ TEST_P(InstCompressed, swsp) { addi t6, t6, 0xAA # 0x15400AA c.swsp t6, 4(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x000000AA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x15400AA000000AA); } @@ -103,9 +103,9 @@ TEST_P(InstCompressed, sdsp) { addi t6, t6, 0xAA # 0x15400AA c.sdsp t6, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); } @@ -121,9 +121,9 @@ TEST_P(InstCompressed, fsdsp) { fmv.d.x f8, t6 c.fsdsp f8, 8(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x00000000000000AA); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 8), 0x00000000015400AA); } @@ -199,9 +199,9 @@ TEST_P(InstCompressed, addi4spn) { c.addi4spn x9, x2, 12 )"); EXPECT_EQ(getGeneralRegister(8), - process_->getInitialStackPointer() + 4); + process_->getStackPointer() + 4); EXPECT_EQ(getGeneralRegister(9), - process_->getInitialStackPointer() + 12); + process_->getStackPointer() + 12); } TEST_P(InstCompressed, sw) { @@ -433,9 +433,9 @@ TEST_P(InstCompressed, addi16sp) { mv x9, x2 )"); EXPECT_EQ(getGeneralRegister(8), - process_->getInitialStackPointer()); + process_->getStackPointer()); EXPECT_EQ(getGeneralRegister(9), - process_->getInitialStackPointer() + 16); + process_->getStackPointer() + 16); } TEST_P(InstCompressed, slli) { diff --git a/test/regression/riscv/instructions/store.cc b/test/regression/riscv/instructions/store.cc index b53a396d88..3f00b3c4bc 100644 --- a/test/regression/riscv/instructions/store.cc +++ b/test/regression/riscv/instructions/store.cc @@ -78,7 +78,7 @@ TEST_P(InstStore, sw) { EXPECT_EQ(getGeneralRegister(10), 64); EXPECT_EQ(getMemoryValue(64), 0xAAADBE000000AA78); EXPECT_EQ(getMemoryValue(69), 0x0087015400AAADBE); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x5400AA00); } @@ -108,7 +108,7 @@ TEST_P(InstStore, sd) { EXPECT_EQ(getGeneralRegister(10), 68); EXPECT_EQ(getMemoryValue(64), 0x0154000000AA5678); EXPECT_EQ(getMemoryValue(68), 0x8765000001540000); - EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 4), + EXPECT_EQ(getMemoryValue(process_->getStackPointer() + 4), 0x000154000000AA01); } From 1e43fd3212b2fdcbce784a029f485a9422a9d14e Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 13:41:18 +0000 Subject: [PATCH 061/115] Rever Linux.getInitialStackPointer --- src/include/simeng/kernel/Linux.hh | 2 +- src/lib/arch/aarch64/Architecture.cc | 2 +- src/lib/arch/riscv/Architecture.cc | 2 +- src/lib/kernel/Linux.cc | 2 +- test/regression/aarch64/MicroOperation.cc | 192 ++++-------- test/regression/aarch64/SmokeTest.cc | 6 +- test/regression/aarch64/instructions/store.cc | 291 ++++++------------ .../riscv/instructions/compressed.cc | 15 +- 8 files changed, 172 insertions(+), 340 deletions(-) diff --git a/src/include/simeng/kernel/Linux.hh b/src/include/simeng/kernel/Linux.hh index 9e859547aa..0908d59006 100644 --- a/src/include/simeng/kernel/Linux.hh +++ b/src/include/simeng/kernel/Linux.hh @@ -134,7 +134,7 @@ class Linux { void createProcess(const LinuxProcess& process); /** Retrieve the initial stack pointer. */ - uint64_t getStackPointer() const; + uint64_t getInitialStackPointer() const; /** brk syscall: change data segment size. Sets the program break to * `addr` if reasonable, and returns the program break. */ diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 2b08b1b44c..5fa77159b4 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -245,7 +245,7 @@ ProcessStateChange Architecture::getInitialState() const { // Set ProcessStateChange type changes.type = ChangeType::REPLACEMENT; - uint64_t stackPointer = linux_.getStackPointer(); + uint64_t stackPointer = linux_.getInitialStackPointer(); // Set the stack pointer register changes.modifiedRegisters.push_back({RegisterType::GENERAL, 31}); changes.modifiedRegisterValues.push_back(stackPointer); diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 11338bfdb8..344ef8c0e7 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -274,7 +274,7 @@ ProcessStateChange Architecture::getInitialState() const { // Set ProcessStateChange type changes.type = ChangeType::REPLACEMENT; - uint64_t stackPointer = linux_.getStackPointer(); + uint64_t stackPointer = linux_.getInitialStackPointer(); // Set the stack pointer register changes.modifiedRegisters.push_back({RegisterType::GENERAL, 2}); changes.modifiedRegisterValues.push_back(stackPointer); diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index d8e1a01845..9f0b594114 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -83,7 +83,7 @@ std::string Linux::getSpecialFile(const std::string filename) { return filename; } -uint64_t Linux::getStackPointer() const { +uint64_t Linux::getInitialStackPointer() const { assert(processStates_.size() > 0 && "Attempted to retrieve a stack pointer before creating a process"); diff --git a/test/regression/aarch64/MicroOperation.cc b/test/regression/aarch64/MicroOperation.cc index 117dd15c93..ee93e6a044 100644 --- a/test/regression/aarch64/MicroOperation.cc +++ b/test/regression/aarch64/MicroOperation.cc @@ -647,22 +647,14 @@ TEST_P(MicroOp, storePairD) { stp d4, d5, [sp, #16] stp d6, d7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - -5.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - -3.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 3.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 5.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), - -1.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), - -0.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), - 0.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), - 1.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -3.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 3.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 5.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), -1.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), -0.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 0.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 1.5); } TEST_P(MicroOp, storePairQ) { @@ -754,22 +746,14 @@ TEST_P(MicroOp, storePairS) { stp s4, s5, [sp, #8] stp s6, s7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - -5.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), - -3.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 3.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), - 5.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - -1.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), - -0.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 0.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), - 1.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -5.0f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), -3.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 5.0f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), -0.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 0.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 1.5f); } TEST_P(MicroOp, storePairW) { @@ -790,22 +774,14 @@ TEST_P(MicroOp, storePairW) { stp w4, w5, [sp, #8] stp w6, w7, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), - 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), - 72); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 84); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 96); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1004), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 60); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 996), 72); } TEST_P(MicroOp, storePairX) { @@ -826,22 +802,14 @@ TEST_P(MicroOp, storePairX) { stp x4, x5, [sp, #16] stp x6, x7, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), - 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), - 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), - 72); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); } TEST_P(MicroOp, storeB) { @@ -869,14 +837,10 @@ TEST_P(MicroOp, storeB) { str b2, [sp, #1] str b3, [sp, #-1]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1023), - 0xFE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), - 0xBA); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1021), - 0xCA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 0xAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1023), 0xFE); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1022), 0xBA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1021), 0xCA); } TEST_P(MicroOp, storeD) { @@ -893,14 +857,10 @@ TEST_P(MicroOp, storeD) { str d2, [sp, #8] str d3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - -3.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 3.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - -1.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 1.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 3.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), -1.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 1.5); } TEST_P(MicroOp, storeH) { @@ -999,14 +959,10 @@ TEST_P(MicroOp, storeS) { str s2, [sp, #4] str s3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - -3.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), - 3.0f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - -1.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), - 1.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), -3.0f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 3.0f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), -1.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 1.5f); } TEST_P(MicroOp, storeW) { @@ -1023,14 +979,10 @@ TEST_P(MicroOp, storeW) { str w2, [sp, #4] str w3, [sp, #-4]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), - 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1020), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1012), 36); } TEST_P(MicroOp, storeX) { @@ -1047,14 +999,10 @@ TEST_P(MicroOp, storeX) { str x2, [sp, #8] str x3, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); } TEST_P(MicroOp, storeThenLoad) { @@ -1078,14 +1026,10 @@ TEST_P(MicroOp, storeThenLoad) { ldr x7, [sp, #8] ldr x8, [sp, #-8]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 36); EXPECT_EQ(getGeneralRegister(5), 12); EXPECT_EQ(getGeneralRegister(6), 24); EXPECT_EQ(getGeneralRegister(7), 36); @@ -1117,22 +1061,14 @@ TEST_P(MicroOp, storeThenLoadPair) { ldp x12, x13, [sp, #16] ldp x14, x15, [sp, #-16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 24); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 84); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 96); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), - 36); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), - 48); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), - 60); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), - 72); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 24); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 84); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 96); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 36); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 48); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 976), 60); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 968), 72); EXPECT_EQ(getGeneralRegister(8), 12); EXPECT_EQ(getGeneralRegister(9), 24); EXPECT_EQ(getGeneralRegister(10), 36); diff --git a/test/regression/aarch64/SmokeTest.cc b/test/regression/aarch64/SmokeTest.cc index 057da9d88f..1966e2d159 100644 --- a/test/regression/aarch64/SmokeTest.cc +++ b/test/regression/aarch64/SmokeTest.cc @@ -34,10 +34,8 @@ TEST_P(SmokeTest, stack) { str w0, [sp, -4] str w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 7u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); } // Test that we can store values to the heap diff --git a/test/regression/aarch64/instructions/store.cc b/test/regression/aarch64/instructions/store.cc index 1cfb83173c..00fec526d2 100644 --- a/test/regression/aarch64/instructions/store.cc +++ b/test/regression/aarch64/instructions/store.cc @@ -21,14 +21,10 @@ TEST_P(InstStore, stlr) { stlrb w3, [sp] add sp, sp, #1 )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), - 0x12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), - 0xCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), - 0x34); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); // stlr RUN_AARCH64(R"( @@ -52,12 +48,10 @@ TEST_P(InstStore, stlr) { EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0xFFFFFFFFFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 0xBEEF); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0xBEEF); EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xFFFFFFFF); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 0xBABA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xBABA); } TEST_P(InstStore, strb) { @@ -76,17 +70,12 @@ TEST_P(InstStore, strb) { mov x6, -16 strb w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), - 0x12); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), - 0xCD); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), - 0x34); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 3), 0x12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0xCD); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1), 0x34); EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 18), - 0x12); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 18), 0x12); } TEST_P(InstStore, strh) { @@ -105,18 +94,12 @@ TEST_P(InstStore, strh) { mov x6, -16 strh w1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 6), - 0x1234); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 0xCD89); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), - 0x3401); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), - 0xABAB); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), - 0x1234); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0xABAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 6), 0x1234); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 0xCD89); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 0x3401); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0xABAB); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 0x1234); } TEST_P(InstStore, strd) { @@ -136,18 +119,12 @@ TEST_P(InstStore, strd) { mov x6, -16 str d1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), - 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), - -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), - 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), - -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 2.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 7.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); } TEST_P(InstStore, strq) { @@ -158,16 +135,11 @@ TEST_P(InstStore, strq) { str q0, [sp], -32 str q1, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), - 0.25); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), - 0.25); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 32); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 0.25); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 0.25); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); } TEST_P(InstStore, strs) { @@ -187,17 +159,12 @@ TEST_P(InstStore, strs) { mov x6, -8 str s1, [sp, x6, sxtx] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), - 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), - -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); } TEST_P(InstStore, strw) { @@ -286,8 +253,7 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #15 st1 {v0.b}[12], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), static_cast(1)); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -321,8 +287,7 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #14 st1 {v0.h}[7], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0xab); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), @@ -354,8 +319,7 @@ TEST_P(InstStore, st1_single_struct) { add sp, sp, #12 st1 {v0.s}[3], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 48), 0.5f); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 1); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 2); @@ -380,8 +344,7 @@ TEST_P(InstStore, st1_single_struct) { st1 {v0.d}[1], [sp], x4 st1 {v1.d}[0], [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 16); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 16); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 32), 0.5); EXPECT_EQ(getMemoryValue(getGeneralRegister(31) - 16), 1000UL); @@ -399,8 +362,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b}, [sp], x0 st1 {v0.16b, v1.16b}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 16; i++) { @@ -423,8 +385,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d}, [sp], x0 st1 {v0.2d, v1.2d}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 2; i++) { @@ -447,8 +408,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s}, [sp], x0 st1 {v0.4s, v1.4s}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 32); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 32); for (int i = 0; i < 4; i++) { @@ -473,8 +433,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [sp], x0 st1 {v0.16b, v1.16b, v2.16b, v3.16b}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 16; i++) { @@ -507,8 +466,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [sp], x0 st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 2; i++) { @@ -541,8 +499,7 @@ TEST_P(InstStore, st1_multi_struct) { st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [sp], x0 st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [sp] )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); for (int j = 2; j >= 0; j--) { uint64_t base = getGeneralRegister(31) - (j * 64); for (int i = 0; i < 4; i++) { @@ -586,12 +543,9 @@ TEST_P(InstStore, st1fourv_post) { st1 {v4.2s, v5.2s, v6.2s, v7.2s}, [x1], x2 )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 64); - EXPECT_EQ(getGeneralRegister(0), - process_->getStackPointer() - 32); - EXPECT_EQ(getGeneralRegister(1), - process_->getStackPointer() - 15); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(0), process_->getStackPointer() - 32); + EXPECT_EQ(getGeneralRegister(1), process_->getStackPointer() - 15); for (int i = 0; i < 2; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -642,10 +596,8 @@ TEST_P(InstStore, st1fourv_post) { )"); EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 128); - EXPECT_EQ(getGeneralRegister(0), - process_->getStackPointer() - 64); - EXPECT_EQ(getGeneralRegister(1), - process_->getStackPointer() - 47); + EXPECT_EQ(getGeneralRegister(0), process_->getStackPointer() - 64); + EXPECT_EQ(getGeneralRegister(1), process_->getStackPointer() - 47); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) + (i * 4)), @@ -686,8 +638,7 @@ TEST_P(InstStore, st2_multi_struct) { st2 {v2.4s, v3.4s}, [sp], x1 st2 {v0.4s, v1.4s}, [sp], #32 )"); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer()); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer()); for (int i = 0; i < 4; i++) { EXPECT_EQ( getMemoryValue(getGeneralRegister(31) - 32 + 8 * i), @@ -719,22 +670,14 @@ TEST_P(InstStore, stpd) { stp d3, d0, [sp, 16] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), - 2.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), - -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), - -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), - 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), - 7.5); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), - 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 16.0); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 2.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 2.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 7.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 7.5); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 16.0); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.0); } TEST_P(InstStore, stps) { @@ -749,20 +692,13 @@ TEST_P(InstStore, stps) { stp s2, s3, [sp, 8]! stp s3, s0, [sp, 8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), - 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), - 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 28), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 20), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 12), 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 16.f); EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 2.f); } @@ -772,10 +708,8 @@ TEST_P(InstStore, stpwi) { movz w1, #42 stp w0, w1, [sp, -8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 7u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); } TEST_P(InstStore, stpq) { @@ -790,40 +724,23 @@ TEST_P(InstStore, stpq) { stp q2, q3, [sp, 32]! stp q3, q0, [sp, 32] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 128), - 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 120), - 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 112), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 104), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 96), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 88), - -0.125f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 80), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 72), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), - 7.5f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), - 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), - 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), - 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), - 16.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - 2.f); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 2.f); - EXPECT_EQ(getGeneralRegister(31), - process_->getStackPointer() - 64); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 128), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 120), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 112), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 104), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 96), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 88), -0.125f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 80), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 72), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 64), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 56), 7.5f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 48), 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 40), 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 32), 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 24), 16.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), 2.f); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 2.f); + EXPECT_EQ(getGeneralRegister(31), process_->getStackPointer() - 64); } TEST_P(InstStore, stpx) { @@ -841,18 +758,12 @@ TEST_P(InstStore, stpx) { stp x2, x3, [sp] stp x4, x5, [sp, #16]! )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), - 7u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), - 42u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), - 8u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), - 43u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), - 9u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), - 44u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1024), 7u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1016), 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1008), 8u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 1000), 43u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 992), 9u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 984), 44u); } TEST_P(InstStore, stur) { @@ -860,38 +771,32 @@ TEST_P(InstStore, stur) { movz w0, #42 stur w0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 42u); RUN_AARCH64(R"( movz x0, #42 stur x0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), 42u); RUN_AARCH64(R"( fmov s0, -0.125 stur s0, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), -0.125); RUN_AARCH64(R"( fmov d0, -0.125 stur d0, [sp, #-8] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); RUN_AARCH64(R"( fmov v0.2d, -0.125 stur q0, [sp, #-16] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), - -0.125); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), - -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 16), -0.125); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 8), -0.125); } TEST_P(InstStore, sturh) { @@ -901,10 +806,8 @@ TEST_P(InstStore, sturh) { movz w1, #128 sturh w1, [sp, #-4] )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), - 42u); - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), - 128u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 2), 42u); + EXPECT_EQ(getMemoryValue(process_->getStackPointer() - 4), 128u); } INSTANTIATE_TEST_SUITE_P(AArch64, InstStore, diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 99823a3504..8b9ff332c4 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -87,8 +87,7 @@ TEST_P(InstCompressed, swsp) { addi t6, t6, 0xAA # 0x15400AA c.swsp t6, 4(sp) )"); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), - 0x000000AA); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x000000AA); EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x15400AA000000AA); } @@ -198,10 +197,8 @@ TEST_P(InstCompressed, addi4spn) { c.addi4spn x8, x2, 4 c.addi4spn x9, x2, 12 )"); - EXPECT_EQ(getGeneralRegister(8), - process_->getStackPointer() + 4); - EXPECT_EQ(getGeneralRegister(9), - process_->getStackPointer() + 12); + EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer() + 4); + EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 12); } TEST_P(InstCompressed, sw) { @@ -432,10 +429,8 @@ TEST_P(InstCompressed, addi16sp) { c.addi16sp x2, 16 mv x9, x2 )"); - EXPECT_EQ(getGeneralRegister(8), - process_->getStackPointer()); - EXPECT_EQ(getGeneralRegister(9), - process_->getStackPointer() + 16); + EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer()); + EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 16); } TEST_P(InstCompressed, slli) { From 369d9ab44e2debbad7d9cec04d91bf006bc7a389 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 13:46:49 +0000 Subject: [PATCH 062/115] Fix incorrect formatting --- src/lib/arch/riscv/Instruction_execute.cc | 8 +++---- test/regression/aarch64/instructions/sme.cc | 24 ++++++++++----------- test/regression/riscv/instructions/store.cc | 3 +-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 8bf3eecd9d..9c5778ae55 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -783,8 +783,8 @@ void Instruction::execute() { // case Opcode::RISCV_MULH: {//MULH rd,rs1,rs2 // return executionNYI(); // - // const int64_t rs1 = sourceRegValues[0].get(); - // const int64_t rs2 = sourceRegValues[1].get(); + // const int64_t rs1 = operands[0].get(); + // const int64_t rs2 = operands[1].get(); // results[0] = RegisterValue(mulhiss(rs1, rs2); // break; // } @@ -797,8 +797,8 @@ void Instruction::execute() { // case Opcode::RISCV_MULHSU: {//MULHSU rd,rs1,rs2 // return executionNYI(); // - // const int64_t rs1 = sourceRegValues[0].get(); - // const uint64_t rs2 = sourceRegValues[1].get(); + // const int64_t rs1 = operands[0].get(); + // const uint64_t rs2 = operands[1].get(); // results[0] = RegisterValue(mulhisu(rs1, rs2); // break; // } diff --git a/test/regression/aarch64/instructions/sme.cc b/test/regression/aarch64/instructions/sme.cc index d553821771..847b1cb604 100644 --- a/test/regression/aarch64/instructions/sme.cc +++ b/test/regression/aarch64/instructions/sme.cc @@ -300,9 +300,9 @@ TEST_P(InstSme, st1d) { st1d {za1h.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - - 4095 + (i * 8)), - src[i % 2]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), + src[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src[i % 2]); } @@ -361,9 +361,9 @@ TEST_P(InstSme, st1d) { st1d {za1v.d[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 64); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - - 4095 + (i * 8)), - src_vert[i % 2]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 8)), + src_vert[i % 2]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 8)), src_vert[i % 2]); } @@ -424,9 +424,9 @@ TEST_P(InstSme, st1w) { st1w {za1h.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - - 4095 + (i * 4)), - src[i % 4]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), + src[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src[i % 4]); } @@ -485,9 +485,9 @@ TEST_P(InstSme, st1w) { st1w {za1v.s[w12, 1]}, p0, [x4] )"); for (int i = 0; i < (SVL / 32); i++) { - EXPECT_EQ(getMemoryValue(process_->getStackPointer() - - 4095 + (i * 4)), - src_vert[i % 4]); + EXPECT_EQ( + getMemoryValue(process_->getStackPointer() - 4095 + (i * 4)), + src_vert[i % 4]); EXPECT_EQ(getMemoryValue((SVL / 8) + (i * 4)), src_vert[i % 4]); } diff --git a/test/regression/riscv/instructions/store.cc b/test/regression/riscv/instructions/store.cc index 3f00b3c4bc..4261377f71 100644 --- a/test/regression/riscv/instructions/store.cc +++ b/test/regression/riscv/instructions/store.cc @@ -78,8 +78,7 @@ TEST_P(InstStore, sw) { EXPECT_EQ(getGeneralRegister(10), 64); EXPECT_EQ(getMemoryValue(64), 0xAAADBE000000AA78); EXPECT_EQ(getMemoryValue(69), 0x0087015400AAADBE); - EXPECT_EQ(getMemoryValue(process_->getStackPointer()), - 0x5400AA00); + EXPECT_EQ(getMemoryValue(process_->getStackPointer()), 0x5400AA00); } TEST_P(InstStore, sd) { From 8304f1e2b6b4c88570a54a65f6a09acfa2059655 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 18:26:33 +0000 Subject: [PATCH 063/115] Add comments --- src/lib/arch/riscv/InstructionMetadata.cc | 4 ++-- src/lib/arch/riscv/Instruction_decode.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 7af63bc4a8..054b5773e2 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -15,8 +15,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitSourceCount(insn.detail->regs_read_count), implicitDestinationCount(insn.detail->regs_write_count), operandCount(insn.detail->riscv.op_count) { - // std::memcpy(encoding, insn.bytes, sizeof(encoding)); - + // Populate 'encoding' field with correct bytes dependent on whether this is a + // compressed instruction setLength(insn.size); std::memset(encoding, 0, 4); std::memcpy(encoding, insn.bytes, insn.size); diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 6ca1ce5925..9ccbfaad4a 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -210,7 +210,7 @@ void Instruction::decode() { operandsPending++; } - // First operands never immediate + // First operand is never immediate else if (i > 0 && op.type == RISCV_OP_IMM) { imm = op.imm; } From 7d383286e0f061c8a2c4744f2339ed1c9a658264 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 29 Jan 2024 18:27:46 +0000 Subject: [PATCH 064/115] Rename imm to imm_ --- src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/riscv/Instruction_address.cc | 4 +- src/lib/arch/riscv/Instruction_decode.cc | 4 +- src/lib/arch/riscv/Instruction_execute.cc | 50 ++++++++++---------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 4bd1f6768f..078ef126f5 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -201,7 +201,7 @@ class Instruction : public simeng::Instruction { std::array operands; /** Extracted value of current immediate from metadata */ - int64_t imm = 0; + int64_t imm_ = 0; /** An array of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 300354cd4e..1b265d983c 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -37,13 +37,13 @@ span Instruction::generateAddresses() { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[0].get() + imm; + address = operands[0].get() + imm_; } else { assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[1].get() + imm; + address = operands[1].get() + imm_; } // Atomics diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 9ccbfaad4a..09ba1050b8 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -205,14 +205,14 @@ void Instruction::decode() { else if (i > 0 && op.type == RISCV_OP_MEM) { // Memory operand sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); - imm = op.mem.disp; + imm_ = op.mem.disp; sourceRegisterCount++; operandsPending++; } // First operand is never immediate else if (i > 0 && op.type == RISCV_OP_IMM) { - imm = op.imm; + imm_ = op.imm; } } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 9c5778ae55..66d78b09b3 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -234,7 +234,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt const int64_t rs1 = operands[0].get(); - const int64_t shamt = imm & 63; // Only use lowest 6 bits + const int64_t shamt = imm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); results[0] = RegisterValue(out, 8); break; @@ -249,7 +249,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt const int32_t rs1 = operands[0].get(); - const int32_t shamt = imm & 63; // Only use lowest 6 bits + const int32_t shamt = imm_ & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); results[0] = RegisterValue(out, 8); break; @@ -264,7 +264,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt const uint64_t rs1 = operands[0].get(); - const uint64_t shamt = imm & 63; // Only use lowest 6 bits + const uint64_t shamt = imm_ & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -279,7 +279,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt const uint32_t rs1 = operands[0].get(); - const uint32_t shamt = imm & 63; // Only use lowest 6 bits + const uint32_t shamt = imm_ & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); results[0] = RegisterValue(out, 8); break; @@ -294,7 +294,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt const int64_t rs1 = operands[0].get(); - const int64_t shamt = imm & 63; // Only use lowest 6 bits + const int64_t shamt = imm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -309,7 +309,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt const int32_t rs1 = operands[0].get(); - const int32_t shamt = imm & 63; // Only use lowest 6 bits + const int32_t shamt = imm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -330,14 +330,14 @@ void Instruction::execute() { } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = imm; + const uint64_t rs2 = imm_; uint64_t out = static_cast(rs1 + rs2); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm const int32_t rs1 = operands[0].get(); - const int32_t sourceImm = imm; + const int32_t sourceImm = imm_; uint64_t out = signExtendW(rs1 + sourceImm); results[0] = RegisterValue(out, 8); break; @@ -356,14 +356,14 @@ void Instruction::execute() { results[0] = RegisterValue(out, 8); break; } - case Opcode::RISCV_LUI: { // LUI rd,imm - uint64_t out = signExtendW(imm << 12); // Shift into upper 20 bits + case Opcode::RISCV_LUI: { // LUI rd,imm + uint64_t out = signExtendW(imm_ << 12); // Shift into upper 20 bits results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AUIPC: { // AUIPC rd,imm const int64_t pc = instructionAddress_; - const int64_t uimm = signExtendW(imm << 12); // Shift into upper 20 bits + const int64_t uimm = signExtendW(imm_ << 12); // Shift into upper 20 bits uint64_t out = static_cast(pc + uimm); results[0] = RegisterValue(out, 8); break; @@ -377,7 +377,7 @@ void Instruction::execute() { } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm; + const uint64_t sourceImm = imm_; uint64_t out = static_cast(rs1 ^ sourceImm); results[0] = RegisterValue(out, 8); break; @@ -391,7 +391,7 @@ void Instruction::execute() { } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm; + const uint64_t sourceImm = imm_; uint64_t out = static_cast(rs1 | sourceImm); results[0] = RegisterValue(out, 8); break; @@ -405,7 +405,7 @@ void Instruction::execute() { } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm; + const uint64_t sourceImm = imm_; uint64_t out = static_cast(rs1 & sourceImm); results[0] = RegisterValue(out, 8); break; @@ -432,7 +432,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm const int64_t rs1 = operands[0].get(); - const int64_t sourceImm = imm; + const int64_t sourceImm = imm_; if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -442,7 +442,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = static_cast(imm); + const uint64_t sourceImm = static_cast(imm_); if (rs1 < sourceImm) { results[0] = RegisterValue(static_cast(1), 8); } else { @@ -454,7 +454,7 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 == rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -466,7 +466,7 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 != rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { // Increase by instruction size to account for compressed instructions @@ -479,7 +479,7 @@ void Instruction::execute() { const int64_t rs1 = operands[0].get(); const int64_t rs2 = operands[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -491,7 +491,7 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -503,7 +503,7 @@ void Instruction::execute() { const int64_t rs1 = operands[0].get(); const int64_t rs2 = operands[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -515,7 +515,7 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.lenBytes; @@ -523,15 +523,15 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_JAL: { // JAL rd,imm - branchAddress_ = instructionAddress_ + imm; // Set LSB of result to 0 + case Opcode::RISCV_JAL: { // JAL rd,imm + branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm branchAddress_ = - (operands[0].get() + imm) & ~1; // Set LSB of result to 0 + (operands[0].get() + imm_) & ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); break; From 08cb07e06ddcd7a1bbdd1f01b3890c31745500f2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 30 Jan 2024 12:19:24 +0000 Subject: [PATCH 065/115] Remove comment --- src/include/simeng/kernel/LinuxProcess.hh | 2 +- src/lib/arch/riscv/Architecture.cc | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index cda3de8c0d..d51e5e726a 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -94,7 +94,7 @@ class LinuxProcess { /** Get the entry point. */ uint64_t getEntryPoint() const; - /** Get the initial stack pointer address. */ + /** Get the initial stack pointer. */ uint64_t getStackPointer() const; /** Get the path of the executable. */ diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 344ef8c0e7..0470e6c023 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -21,11 +21,6 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) fesetround(FE_TONEAREST); constantsPool constantsPool; - - // TODO an 'if' clause could be added here to check if compressed instructions - // are allowed based off of config options which selects the corrct cs_mode - // and constants. Currently always rv64gc allowed - constants_.alignMask = constantsPool.alignMaskCompressed; constants_.regWidth = constantsPool.byteLength64; constants_.bytesLimit = constantsPool.bytesLimitCompressed; From 2c00c9f55a950ed7b29c92449f33f9f048ef01d8 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 30 Jan 2024 16:42:16 +0000 Subject: [PATCH 066/115] Cleanup instruction length field --- src/lib/arch/riscv/Architecture.cc | 4 ++-- src/lib/arch/riscv/InstructionMetadata.cc | 23 +++++------------------ src/lib/arch/riscv/InstructionMetadata.hh | 17 ++++++----------- src/lib/arch/riscv/Instruction_execute.cc | 18 ++++++++++-------- 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 0470e6c023..640c6f4256 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -218,7 +218,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, iter = decodeCache.insert({insn, newInsn}).first; } - if (iter->second.getMetadata().lenBytes > bytesAvailable) { + if (iter->second.getMetadata().getInsnLength() > bytesAvailable) { // If cached but too many bytes read. BAIL return 0; } @@ -231,7 +231,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uop->setInstructionAddress(instructionAddress); - return iter->second.getMetadata().lenBytes; + return iter->second.getMetadata().getInsnLength(); } executionInfo Architecture::getExecutionInfo(Instruction& insn) const { diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 054b5773e2..9440386fef 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -17,9 +17,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount(insn.detail->riscv.op_count) { // Populate 'encoding' field with correct bytes dependent on whether this is a // compressed instruction - setLength(insn.size); + insnLengthBytes_ = insn.size; std::memset(encoding, 0, 4); - std::memcpy(encoding, insn.bytes, insn.size); + std::memcpy(encoding, insn.bytes, insnLengthBytes_); // Copy printed output std::strncpy(mnemonic, insn.mnemonic, CS_MNEMONIC_SIZE); @@ -43,12 +43,12 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, opcode(Opcode::RISCV_INSTRUCTION_LIST_END), implicitSourceCount(0), implicitDestinationCount(0), - operandCount(0), - len(INSTR_LENGTH::IL_INVALID) { + operandCount(0) { assert(bytes <= sizeof(encoding)); std::memcpy(encoding, invalidEncoding, bytes); mnemonic[0] = '\0'; operandStr[0] = '\0'; + insnLengthBytes_ = 0; } void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { @@ -474,21 +474,8 @@ void InstructionMetadata::createMemOpPosOne() { operandCount = 2; } -void InstructionMetadata::setLength(uint8_t size) { - lenBytes = size; - switch (size) { - case 2: - len = INSTR_LENGTH::IL_16B; - break; - case 4: - len = INSTR_LENGTH::IL_32B; - break; - default: - len = INSTR_LENGTH::IL_INVALID; - } -} void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { - if (len != INSTR_LENGTH::IL_16B) { + if (insnLengthBytes_ != 2) { return; } diff --git a/src/lib/arch/riscv/InstructionMetadata.hh b/src/lib/arch/riscv/InstructionMetadata.hh index ef8705b990..9a641353f9 100644 --- a/src/lib/arch/riscv/InstructionMetadata.hh +++ b/src/lib/arch/riscv/InstructionMetadata.hh @@ -15,8 +15,6 @@ namespace Opcode { #include "RISCVGenInstrInfo.inc" } // namespace Opcode -enum class INSTR_LENGTH { IL_16B, IL_32B, IL_INVALID }; - /** A simplified RISC-V-only version of the Capstone instruction structure. */ struct InstructionMetadata { public: @@ -32,11 +30,14 @@ struct InstructionMetadata { return metadataException_; } - /* Returns a bool stating whether an exception has been encountered */ + /* Returns a bool stating whether an exception has been encountered. */ bool getMetadataExceptionEncountered() const { return metadataExceptionEncountered_; } + /* Returns the length of the instruction in bytes. */ + uint8_t getInsnLength() const { return insnLengthBytes_; } + /** The maximum operand string length as defined in Capstone */ static const size_t MAX_OPERAND_STR_LENGTH = sizeof(cs_insn::op_str) / sizeof(char); @@ -87,12 +88,6 @@ struct InstructionMetadata { /** The number of explicit operands. */ uint8_t operandCount; - /** The instruction length for variable instruction length support. */ - INSTR_LENGTH len; - - /** The length of the instruction encoding in bytes. */ - uint8_t lenBytes; - private: /** Detect instruction aliases and update metadata to match the de-aliased * instruction. */ @@ -128,8 +123,8 @@ struct InstructionMetadata { /** Whether an exception has been encountered. */ bool metadataExceptionEncountered_ = false; - /** Set the byte length of instruction */ - void setLength(uint8_t size); + /** The length of the instruction encoding in bytes. */ + uint8_t insnLengthBytes_; }; } // namespace riscv diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 66d78b09b3..6946196c3b 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -457,7 +457,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -470,7 +470,7 @@ void Instruction::execute() { branchTaken_ = true; } else { // Increase by instruction size to account for compressed instructions - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -482,7 +482,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -494,7 +494,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -506,7 +506,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -518,7 +518,7 @@ void Instruction::execute() { branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; } else { - branchAddress_ = instructionAddress_ + metadata.lenBytes; + branchAddress_ = instructionAddress_ + metadata.getInsnLength(); branchTaken_ = false; } break; @@ -526,14 +526,16 @@ void Instruction::execute() { case Opcode::RISCV_JAL: { // JAL rd,imm branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 branchTaken_ = true; - results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); + results[0] = + RegisterValue(instructionAddress_ + metadata.getInsnLength(), 8); break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm branchAddress_ = (operands[0].get() + imm_) & ~1; // Set LSB of result to 0 branchTaken_ = true; - results[0] = RegisterValue(instructionAddress_ + metadata.lenBytes, 8); + results[0] = + RegisterValue(instructionAddress_ + metadata.getInsnLength(), 8); break; } // TODO EBREAK From ba0b4195103f9e7475d673e13113a43eb0cd7017 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 31 Jan 2024 17:30:04 +0000 Subject: [PATCH 067/115] Update stack terminology --- src/include/simeng/kernel/LinuxProcess.hh | 6 +++--- src/lib/pipeline/FetchUnit.cc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index d51e5e726a..dbddb31245 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -40,7 +40,7 @@ uint64_t alignToBoundary(uint64_t value, uint64_t boundary); * * The constructed process follows a typical layout: * - * |---------------| <- start/top of stack + * |---------------| <- start/bottom of stack * | Stack | stack grows downwards * |-v-----------v-| * | | @@ -76,7 +76,7 @@ class LinuxProcess { /** Get the address of the start of the heap region. */ uint64_t getHeapStart() const; - /** Get the address of the top of the stack. */ + /** Get the address of the bottom of the stack. */ uint64_t getStackStart() const; /** Get the address of the start of the mmap region. */ @@ -134,7 +134,7 @@ class LinuxProcess { /** The page size of the process memory. */ const uint64_t pageSize_ = 4096; - /** The address of the head/bottom of the stack */ + /** The address of the head/top of the stack */ uint64_t stackPointer_; /** The process image size. */ diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 426d19cfb8..5ab300a153 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -172,11 +172,11 @@ void FetchUnit::tick() { assert(bytesRead <= bufferedBytes_ && "Predecode consumed more bytes than were available"); - // Increment the offset, decrement available bytes + // Increment the offset, decrement available bytes bufferOffset += bytesRead; - bufferedBytes_ -= bytesRead; + if (!prediction.taken) { // Predicted as not taken; increment PC to next instruction pc_ += bytesRead; From 3738db83f1d7b2fd72a3f45cfe6a4e7b6c516349 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 1 Feb 2024 15:41:31 +0000 Subject: [PATCH 068/115] Remove TODOs --- src/lib/pipeline/FetchUnit.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 5ab300a153..dfd9fd2887 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -61,7 +61,6 @@ void FetchUnit::tick() { uint8_t bufferOffset; // Check if more instruction data is required - // TODO Unsure of whether this should be minimum instruction size instead if (bufferedBytes_ < isa_.getMaxInstructionSize()) { // Calculate the address of the next fetch block uint64_t blockAddress; @@ -98,7 +97,6 @@ void FetchUnit::tick() { std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, blockSize_ - bufferOffset); - // TODO can bufferedBytes_ go above the block size? bufferedBytes_ += blockSize_ - bufferOffset; buffer = fetchBuffer_; @@ -110,6 +108,7 @@ void FetchUnit::tick() { bufferOffset = 0; } + // Potentially a redundant check considering the above // Check we have enough data to begin decoding if (bufferedBytes_ < isa_.getMaxInstructionSize()) return; From f527e050e3f3af3ae4a37253165f529f9ffa2049 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 2 Feb 2024 16:33:29 +0000 Subject: [PATCH 069/115] Prevent segfault in fcvtzu test, unsure why fix works --- test/regression/aarch64/instructions/float.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/regression/aarch64/instructions/float.cc b/test/regression/aarch64/instructions/float.cc index 23c174407f..2e39bb0cab 100644 --- a/test/regression/aarch64/instructions/float.cc +++ b/test/regression/aarch64/instructions/float.cc @@ -539,8 +539,8 @@ TEST_P(InstFloat, fcvtzu) { dheap[1] = -42.76; dheap[2] = -0.125; dheap[3] = 321.5; - dheap[4] = std::nan(0); - dheap[5] = -std::nan(0); + dheap[4] = std::numeric_limits::quiet_NaN(); + dheap[5] = -std::numeric_limits::quiet_NaN(); dheap[6] = INFINITY; dheap[7] = -INFINITY; dheap[8] = 4294967296.0; // uint32_max + 1 @@ -654,8 +654,8 @@ TEST_P(InstFloat, fcvtzu) { fheap[1] = -42.76f; fheap[2] = -0.125f; fheap[3] = 321.5f; - fheap[4] = std::nanf(0); - fheap[5] = -std::nanf(0); + fheap[4] = std::numeric_limits::quiet_NaN(); + fheap[5] = -std::numeric_limits::quiet_NaN(); fheap[6] = INFINITY; fheap[7] = -INFINITY; fheap[8] = 4294967296.0; // uint32_max + 1 From 4f6ee8fc12d734d3b900faae7728930842f4d8f0 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 2 Feb 2024 18:06:39 +0000 Subject: [PATCH 070/115] Don't attempt to predecode if max instruction length bytes not available --- src/lib/arch/riscv/Architecture.cc | 16 ---------------- src/lib/arch/riscv/InstructionMetadata.cc | 2 +- src/lib/pipeline/FetchUnit.cc | 17 +++++++++-------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 0745ab8c9d..07e0dca32b 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -193,17 +193,6 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, bool success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); - if (!success || rawInsn.opcode == RISCV_INS_INVALID) { - // Invalid decoding, potentially read over the end of the valid buffer. - // BAIL. Do not add to cache as may be incorrect data - return 0; - } - - if (rawInsn.size > bytesAvailable) { - // Too many bytes read. BAIL - return 0; - } - auto metadata = success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding); @@ -218,11 +207,6 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, iter = decodeCache.insert({insn, newInsn}).first; } - if (iter->second.getMetadata().getInsnLength() > bytesAvailable) { - // If cached but too many bytes read. BAIL - return 0; - } - output.resize(1); auto& uop = output[0]; diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 9440386fef..6523dc92e8 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -48,7 +48,7 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, std::memcpy(encoding, invalidEncoding, bytes); mnemonic[0] = '\0'; operandStr[0] = '\0'; - insnLengthBytes_ = 0; + insnLengthBytes_ = 4; } void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index dfd9fd2887..05cf00266c 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -113,6 +113,7 @@ void FetchUnit::tick() { if (bufferedBytes_ < isa_.getMaxInstructionSize()) return; auto outputSlots = output_.getTailSlots(); + for (size_t slot = 0; slot < output_.getWidth(); slot++) { auto& macroOp = outputSlots[slot]; @@ -121,12 +122,8 @@ void FetchUnit::tick() { // If predecode fails, bail and wait for more data if (bytesRead == 0) { - // TODO should be minimum? - // Assertion currently commented as bytesRead == 0 is used to force - // finishing tick on compressed instruction edge cases which are correct - // behaviour - // assert(bufferedBytes_ < isa_.getMaxInstructionSize() && - // "unexpected predecode failure"); + assert(bufferedBytes_ < isa_.getMaxInstructionSize() && + "unexpected predecode failure"); break; } @@ -158,6 +155,7 @@ void FetchUnit::tick() { // loopBoundaryAddress_ has been fetched whilst filling the loop // buffer. Stop filling as loop body has been recorded and begin to // supply decode unit with instructions from the loop buffer + loopBufferState_ = LoopBufferState::SUPPLYING; bufferedBytes_ = 0; break; @@ -198,8 +196,11 @@ void FetchUnit::tick() { break; } - // Too few bytes remaining in buffer to continue - if (bufferedBytes_ == 0) { + // Too few bytes remaining in buffer to continue. + // Don't attempt to predecode if not enough bytes for largest instruction + // encoding. Potentially misses ability to predecode compressed instruction + // but prevents messy handling logic + if (bufferedBytes_ < isa_.getMaxInstructionSize()) { break; } } From f38e9cbedd50a41a5b78930c99208a2c1161de9d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 5 Feb 2024 21:51:18 +0000 Subject: [PATCH 071/115] Nan fix in line with PR 381 --- test/regression/aarch64/instructions/float.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/regression/aarch64/instructions/float.cc b/test/regression/aarch64/instructions/float.cc index 2e39bb0cab..03f3f799df 100644 --- a/test/regression/aarch64/instructions/float.cc +++ b/test/regression/aarch64/instructions/float.cc @@ -539,8 +539,8 @@ TEST_P(InstFloat, fcvtzu) { dheap[1] = -42.76; dheap[2] = -0.125; dheap[3] = 321.5; - dheap[4] = std::numeric_limits::quiet_NaN(); - dheap[5] = -std::numeric_limits::quiet_NaN(); + dheap[4] = std::nan(""); + dheap[5] = -std::nan(""); dheap[6] = INFINITY; dheap[7] = -INFINITY; dheap[8] = 4294967296.0; // uint32_max + 1 @@ -654,8 +654,8 @@ TEST_P(InstFloat, fcvtzu) { fheap[1] = -42.76f; fheap[2] = -0.125f; fheap[3] = 321.5f; - fheap[4] = std::numeric_limits::quiet_NaN(); - fheap[5] = -std::numeric_limits::quiet_NaN(); + fheap[4] = std::nanf(""); + fheap[5] = -std::nanf(""); fheap[6] = INFINITY; fheap[7] = -INFINITY; fheap[8] = 4294967296.0; // uint32_max + 1 From 8c67ac57d007025f898276bb8020d46ef23de950 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 5 Feb 2024 22:53:33 +0000 Subject: [PATCH 072/115] Update predecode to predecode for compressed instructions meaning no need for early bail. Proper usage of decode cache. Debug prints left in --- src/include/simeng/arch/Architecture.hh | 6 +- .../simeng/arch/aarch64/Architecture.hh | 5 +- src/include/simeng/arch/riscv/Architecture.hh | 5 +- src/lib/arch/aarch64/Architecture.cc | 6 +- src/lib/arch/riscv/Architecture.cc | 68 +++++++++++++++++-- src/lib/pipeline/FetchUnit.cc | 9 ++- test/unit/MockArchitecture.hh | 3 +- 7 files changed, 84 insertions(+), 18 deletions(-) diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 9a2d4c69bc..32bdbe2853 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -65,9 +65,9 @@ class Architecture { * Writes into the supplied macro-op vector, and returns the number of bytes * consumed to produce it; a value of 0 indicates too few bytes were present * for a valid decoding. */ - virtual uint8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const = 0; + virtual int8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const = 0; /** Returns a zero-indexed register tag for a system register encoding. */ virtual int32_t getSystemRegisterTag(uint16_t reg) const = 0; diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 1204b1f915..656ca7d5ae 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -24,9 +24,8 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (always 4), * and writes into the supplied macro-op vector. */ - uint8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const override; + int8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, MacroOp& output) const override; /** Returns a zero-indexed register tag for a system register encoding. * Returns -1 in the case that the system register has no mapping. */ diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index ebde07837f..50d2992c83 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -29,9 +29,8 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (0 if * failure), and writes into the supplied macro-op vector. */ - uint8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const override; + int8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, MacroOp& output) const override; /** Returns a zero-indexed register tag for a system register encoding. */ int32_t getSystemRegisterTag(uint16_t reg) const override; diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 5fa77159b4..141a5503bd 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -144,9 +144,9 @@ Architecture::~Architecture() { SVCRval_ = 0; } -uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const { +int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by Armv9.2-a if (instructionAddress & 0x3) { // Consume 1-byte and raise a misaligned PC exception diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 07e0dca32b..1a4a171d9a 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -152,9 +152,9 @@ Architecture::~Architecture() { groupExecutionInfo_.clear(); } -uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const { +int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by RISC-V // 2-byte when Compressed ISA is supported if (instructionAddress & constants_.alignMask) { @@ -177,9 +177,30 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uint32_t insn; memcpy(&insn, ptr, 4); + // Predecode bytes to determine whether we have a compressed instruction. + // This will allow continuation if a compressed instruction is in the last 2 + // bytes of a fetch block, but will request more data if only half of a + // non-compressed instruction is present + uint8_t predictedBytes = 0; + if ((insn & 0b11) != 0b11) { + // 2 byte - compressed + predictedBytes = 2; + insn = insn & 0xFFFF; + } else { + // 4 byte + predictedBytes = 4; + if (bytesAvailable < 4) { + // Not enough bytes available, bail + return -1; + } + } + + bool success; // Try to find the decoding in the decode cache auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { + std::cerr << "size " << decodeCache.size() << std::endl; + // No decoding present. Generate a fresh decoding, and add to cache cs_insn rawInsn; cs_detail rawDetail; @@ -190,7 +211,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, const uint8_t* encoding = reinterpret_cast(ptr); - bool success = + success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); auto metadata = @@ -203,9 +224,48 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, Instruction newInsn(*this, metadataCache.front()); // Set execution information for this instruction newInsn.setExecutionInfo(getExecutionInfo(newInsn)); + + if (newInsn.getMetadata().opcode == Opcode::RISCV_INSTRUCTION_LIST_END) { + // Often incorrect predicted number of bytes when using garbage data. + // Update `insn` so cache can be used properly + predictedBytes = 4; + memcpy(&insn, ptr, 4); + } + + // if (newInsn.getMetadata().getInsnLength() == 2) { + // std::cerr << std::hex << "insn=" << insn << std::dec << std::endl; + // std::cerr << std::hex + // << "encoding=" << (int)newInsn.getMetadata().encoding[0] + // << " " + // << (int)newInsn.getMetadata().encoding[1] << " " + // << (int)newInsn.getMetadata().encoding[2] << " " + // << (int)newInsn.getMetadata().encoding[3] << std::dec + // << std::endl; + // } + // Cache the instruction iter = decodeCache.insert({insn, newInsn}).first; } + // else if (predictedBytes == 2) { + // std::cerr << "cached compressed instruction = " << std::hex << insn + // << std::dec << std::endl; + // } + + // if ((predictedBytes != iter->second.getMetadata().getInsnLength())) { + // //&& iter->second.getMetadata().opcode != 450) { + // std::cerr << "" << std::endl; + // std::cerr << "CONTRADICION pred=" << (int)predictedBytes << " ACtual " + // << (int)iter->second.getMetadata().getInsnLength() << " insns" + // << std::endl; + // std::cerr << "opcode=" << (int)iter->second.getMetadata().opcode << " " + // << iter->second.getMetadata().operandStr << std::endl; + // std::cerr << std::hex << "insn=" << insn << std::dec << std::endl; + // std::cerr << std::hex + // << "encoding=" << (int)iter->second.getMetadata().encoding[0] + // << " " << (int)iter->second.getMetadata().encoding[1] << " " + // << (int)iter->second.getMetadata().encoding[2] << std::dec + // << std::endl; + // } output.resize(1); auto& uop = output[0]; diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 05cf00266c..81e803c75f 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -127,6 +127,13 @@ void FetchUnit::tick() { break; } + // Expected predecode failure, bail and wait for more data + if (bytesRead < 0) { + // std::cerr << "Early expected bail" << std::endl; + + break; + } + // Create branch prediction after identifying instruction type // (e.g. RET, BL, etc). BranchPrediction prediction = {false, 0}; @@ -200,7 +207,7 @@ void FetchUnit::tick() { // Don't attempt to predecode if not enough bytes for largest instruction // encoding. Potentially misses ability to predecode compressed instruction // but prevents messy handling logic - if (bufferedBytes_ < isa_.getMaxInstructionSize()) { + if (bufferedBytes_ == 0) { break; } } diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index 0df643ee9e..a86615ed45 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -10,7 +10,8 @@ class MockArchitecture : public arch::Architecture { public: MOCK_CONST_METHOD4(predecode, uint8_t(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, MacroOp& output)); + uint64_t instructionAddress, MacroOp& output)) + int8_tconst void* uint8_tuint64_tMacroOp&; MOCK_CONST_METHOD1(canRename, bool(Register reg)); MOCK_CONST_METHOD1(getSystemRegisterTag, int32_t(uint16_t reg)); MOCK_CONST_METHOD3(handleException, From 21b06de9819c9032e129022fa0d48db9ca2ab268 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 6 Feb 2024 22:09:43 +0000 Subject: [PATCH 073/115] Update invalid instruction bits as now decodes as C.NOP --- test/unit/MockArchitecture.hh | 5 ++--- test/unit/riscv/ArchitectureTest.cc | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index a86615ed45..8e8a73ad63 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -9,9 +9,8 @@ namespace simeng { class MockArchitecture : public arch::Architecture { public: MOCK_CONST_METHOD4(predecode, - uint8_t(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, MacroOp& output)) - int8_tconst void* uint8_tuint64_tMacroOp&; + int8_t(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, MacroOp& output)); MOCK_CONST_METHOD1(canRename, bool(Register reg)); MOCK_CONST_METHOD1(getSystemRegisterTag, int32_t(uint16_t reg)); MOCK_CONST_METHOD3(handleException, diff --git a/test/unit/riscv/ArchitectureTest.cc b/test/unit/riscv/ArchitectureTest.cc index a934232fe4..09c2f6c13d 100644 --- a/test/unit/riscv/ArchitectureTest.cc +++ b/test/unit/riscv/ArchitectureTest.cc @@ -62,7 +62,7 @@ class RiscVArchitectureTest : public testing::Test { // addi sp, ra, 2000 std::array validInstrBytes = {0x13, 0x81, 0x00, 0x7d}; - std::array invalidInstrBytes = {0x7d, 0x00, 0x81, 0xbb}; + std::array invalidInstrBytes = {0x7f, 0x00, 0x81, 0xbb}; std::unique_ptr arch; kernel::Linux kernel; From 76757ccf08dec3e4be304396d01f6d5ad45cd167 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 6 Feb 2024 22:30:18 +0000 Subject: [PATCH 074/115] Remove debug prints and add assertion --- src/lib/arch/riscv/Architecture.cc | 55 ++++++++++-------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 1a4a171d9a..95e74cb897 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -181,14 +181,21 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, // This will allow continuation if a compressed instruction is in the last 2 // bytes of a fetch block, but will request more data if only half of a // non-compressed instruction is present + +#ifndef NDEBUG uint8_t predictedBytes = 0; if ((insn & 0b11) != 0b11) { - // 2 byte - compressed predictedBytes = 2; + } else { + predictedBytes = 4; + } +#endif + + if ((insn & 0b11) != 0b11) { + // 2 byte - compressed insn = insn & 0xFFFF; } else { // 4 byte - predictedBytes = 4; if (bytesAvailable < 4) { // Not enough bytes available, bail return -1; @@ -199,8 +206,6 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, // Try to find the decoding in the decode cache auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { - std::cerr << "size " << decodeCache.size() << std::endl; - // No decoding present. Generate a fresh decoding, and add to cache cs_insn rawInsn; cs_detail rawDetail; @@ -226,46 +231,22 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, newInsn.setExecutionInfo(getExecutionInfo(newInsn)); if (newInsn.getMetadata().opcode == Opcode::RISCV_INSTRUCTION_LIST_END) { - // Often incorrect predicted number of bytes when using garbage data. - // Update `insn` so cache can be used properly + // Often incorrect predicted number of bytes when using garbage data. That + // doesn't get disassembled as invalid. Update `insn` so cache can be used + // properly +#ifndef NDEBUG predictedBytes = 4; +#endif memcpy(&insn, ptr, 4); } - // if (newInsn.getMetadata().getInsnLength() == 2) { - // std::cerr << std::hex << "insn=" << insn << std::dec << std::endl; - // std::cerr << std::hex - // << "encoding=" << (int)newInsn.getMetadata().encoding[0] - // << " " - // << (int)newInsn.getMetadata().encoding[1] << " " - // << (int)newInsn.getMetadata().encoding[2] << " " - // << (int)newInsn.getMetadata().encoding[3] << std::dec - // << std::endl; - // } - // Cache the instruction iter = decodeCache.insert({insn, newInsn}).first; } - // else if (predictedBytes == 2) { - // std::cerr << "cached compressed instruction = " << std::hex << insn - // << std::dec << std::endl; - // } - - // if ((predictedBytes != iter->second.getMetadata().getInsnLength())) { - // //&& iter->second.getMetadata().opcode != 450) { - // std::cerr << "" << std::endl; - // std::cerr << "CONTRADICION pred=" << (int)predictedBytes << " ACtual " - // << (int)iter->second.getMetadata().getInsnLength() << " insns" - // << std::endl; - // std::cerr << "opcode=" << (int)iter->second.getMetadata().opcode << " " - // << iter->second.getMetadata().operandStr << std::endl; - // std::cerr << std::hex << "insn=" << insn << std::dec << std::endl; - // std::cerr << std::hex - // << "encoding=" << (int)iter->second.getMetadata().encoding[0] - // << " " << (int)iter->second.getMetadata().encoding[1] << " " - // << (int)iter->second.getMetadata().encoding[2] << std::dec - // << std::endl; - // } + + assert( + predictedBytes == iter->second.getMetadata().getInsnLength() && + "[SimEng::predecode] Predicted bytes doesn't march disassembled bytes"); output.resize(1); auto& uop = output[0]; From cf80e207b79fa91496c44f83a062c7bc31dd61c3 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 7 Feb 2024 13:42:46 +0000 Subject: [PATCH 075/115] Update comments --- src/lib/arch/riscv/Architecture.cc | 10 +++++----- src/lib/arch/riscv/Instruction_address.cc | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 95e74cb897..343d5e21b1 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -191,8 +191,10 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, } #endif + // Check the 2 least significant bits if ((insn & 0b11) != 0b11) { // 2 byte - compressed + // Only use relevant bytes insn = insn & 0xFFFF; } else { // 4 byte @@ -202,7 +204,6 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, } } - bool success; // Try to find the decoding in the decode cache auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { @@ -216,7 +217,7 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, const uint8_t* encoding = reinterpret_cast(ptr); - success = + bool success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); auto metadata = @@ -244,9 +245,8 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, iter = decodeCache.insert({insn, newInsn}).first; } - assert( - predictedBytes == iter->second.getMetadata().getInsnLength() && - "[SimEng::predecode] Predicted bytes doesn't march disassembled bytes"); + assert(predictedBytes == iter->second.getMetadata().getInsnLength() && + "[SimEng:predecode] Predicted bytes don't match disassembled bytes"); output.resize(1); auto& uop = output[0]; diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 1b265d983c..b9223eabaa 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -15,14 +15,14 @@ span Instruction::generateAddresses() { uint64_t address; if (isLoad() && isStoreAddress() && isAtomic()) { // Atomics - // Metadata operand[2] corresponds to instruction sourceRegValues[1] + // Metadata operands[2] corresponds to instruction sourceRegValues[1] assert(metadata.operands[2].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); address = operands[1].get(); } else if (isLoad() && isAtomic()) { // Load reserved - // Metadata operand[1] corresponds to instruction sourceRegValues[0] + // Metadata operands[1] corresponds to instruction sourceRegValues[0] assert(metadata.operands[1].type == RISCV_OP_REG && "metadata operand not of correct type during RISC-V address " "generation"); From 80faf6a10ccfdceef78112ec391168925d1b96e2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 8 Feb 2024 09:52:15 +0000 Subject: [PATCH 076/115] Update predecode to handle the last bytes of fetch buffer and invalid decodings --- src/lib/arch/riscv/Architecture.cc | 59 ++++++++++++----------- src/lib/arch/riscv/InstructionMetadata.cc | 4 +- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 343d5e21b1..72a00acc63 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -1,6 +1,7 @@ #include "simeng/arch/riscv/Architecture.hh" #include +#include #include #include #include @@ -173,55 +174,63 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, assert(bytesAvailable >= constants_.bytesLimit && "Fewer than bytes limit supplied to RISC-V decoder"); - // Dereference the instruction pointer to obtain the instruction word - uint32_t insn; - memcpy(&insn, ptr, 4); + // Get the first byte + uint8_t firstByte = *(uint8_t*)ptr; + + uint32_t insn = 0; + size_t size = 4; // Predecode bytes to determine whether we have a compressed instruction. // This will allow continuation if a compressed instruction is in the last 2 // bytes of a fetch block, but will request more data if only half of a // non-compressed instruction is present -#ifndef NDEBUG - uint8_t predictedBytes = 0; - if ((insn & 0b11) != 0b11) { - predictedBytes = 2; - } else { - predictedBytes = 4; - } -#endif - - // Check the 2 least significant bits - if ((insn & 0b11) != 0b11) { + // Check the 2 least significant bits as these determine instruction length + if ((firstByte & 0b11) != 0b11) { // 2 byte - compressed // Only use relevant bytes - insn = insn & 0xFFFF; + // Dereference the instruction pointer to obtain the instruction word + memcpy(&insn, ptr, 2); + size = 2; } else { // 4 byte if (bytesAvailable < 4) { // Not enough bytes available, bail return -1; } + // Dereference the instruction pointer to obtain the instruction word + memcpy(&insn, ptr, 4); } // Try to find the decoding in the decode cache auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { // No decoding present. Generate a fresh decoding, and add to cache +#ifndef NDEBUG + // Struct not initialised which can cause issues but can be slow + cs_insn* rawInsnPointer = (cs_insn*)calloc(1, sizeof(cs_insn)); + cs_insn rawInsn = *rawInsnPointer; + assert(rawInsn.size == 0 && "rawInsn not initialised correctly"); +#else cs_insn rawInsn; +#endif + cs_detail rawDetail; rawInsn.detail = &rawDetail; + // Size requires initialisation in case of capstone failure which won't + // update this value + rawInsn.size = size; - size_t size = 4; uint64_t address = 0; const uint8_t* encoding = reinterpret_cast(ptr); bool success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); + // size now contains size of next instruction in the buffer - auto metadata = - success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding); + auto metadata = success ? InstructionMetadata(rawInsn) + : InstructionMetadata(encoding, rawInsn.size); // Cache the metadata metadataCache.push_front(metadata); @@ -231,21 +240,13 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, // Set execution information for this instruction newInsn.setExecutionInfo(getExecutionInfo(newInsn)); - if (newInsn.getMetadata().opcode == Opcode::RISCV_INSTRUCTION_LIST_END) { - // Often incorrect predicted number of bytes when using garbage data. That - // doesn't get disassembled as invalid. Update `insn` so cache can be used - // properly -#ifndef NDEBUG - predictedBytes = 4; -#endif - memcpy(&insn, ptr, 4); - } - // Cache the instruction iter = decodeCache.insert({insn, newInsn}).first; } - assert(predictedBytes == iter->second.getMetadata().getInsnLength() && + assert(((insn & 0b11) != 0b11 + ? iter->second.getMetadata().getInsnLength() == 2 + : iter->second.getMetadata().getInsnLength() == 4) && "[SimEng:predecode] Predicted bytes don't match disassembled bytes"); output.resize(1); diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 6523dc92e8..232eafb276 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -43,12 +43,12 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, opcode(Opcode::RISCV_INSTRUCTION_LIST_END), implicitSourceCount(0), implicitDestinationCount(0), - operandCount(0) { + operandCount(0), + insnLengthBytes_(bytes) { assert(bytes <= sizeof(encoding)); std::memcpy(encoding, invalidEncoding, bytes); mnemonic[0] = '\0'; operandStr[0] = '\0'; - insnLengthBytes_ = 4; } void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { From 9585677c0fcad1f7d2ae7d21b25f7a38cde73baa Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 8 Feb 2024 11:51:49 +0000 Subject: [PATCH 077/115] Return 0 from predecode --- src/lib/arch/riscv/Architecture.cc | 2 +- src/lib/pipeline/FetchUnit.cc | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 72a00acc63..5150c31348 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -196,7 +196,7 @@ int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, // 4 byte if (bytesAvailable < 4) { // Not enough bytes available, bail - return -1; + return 0; } // Dereference the instruction pointer to obtain the instruction word memcpy(&insn, ptr, 4); diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 81e803c75f..3899254c67 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -127,13 +127,6 @@ void FetchUnit::tick() { break; } - // Expected predecode failure, bail and wait for more data - if (bytesRead < 0) { - // std::cerr << "Early expected bail" << std::endl; - - break; - } - // Create branch prediction after identifying instruction type // (e.g. RET, BL, etc). BranchPrediction prediction = {false, 0}; @@ -204,9 +197,6 @@ void FetchUnit::tick() { } // Too few bytes remaining in buffer to continue. - // Don't attempt to predecode if not enough bytes for largest instruction - // encoding. Potentially misses ability to predecode compressed instruction - // but prevents messy handling logic if (bufferedBytes_ == 0) { break; } From d9f5f504519641c3d96d2c7cf6ec45ce27b60e7a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 8 Feb 2024 11:57:34 +0000 Subject: [PATCH 078/115] Revert predecode to int8_t --- src/include/simeng/arch/Architecture.hh | 6 +++--- src/include/simeng/arch/aarch64/Architecture.hh | 5 +++-- src/include/simeng/arch/riscv/Architecture.hh | 5 +++-- src/lib/arch/aarch64/Architecture.cc | 6 +++--- src/lib/arch/riscv/Architecture.cc | 6 +++--- src/lib/pipeline/FetchUnit.cc | 2 +- test/unit/MockArchitecture.hh | 4 ++-- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 32bdbe2853..9a2d4c69bc 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -65,9 +65,9 @@ class Architecture { * Writes into the supplied macro-op vector, and returns the number of bytes * consumed to produce it; a value of 0 indicates too few bytes were present * for a valid decoding. */ - virtual int8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const = 0; + virtual uint8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const = 0; /** Returns a zero-indexed register tag for a system register encoding. */ virtual int32_t getSystemRegisterTag(uint16_t reg) const = 0; diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 656ca7d5ae..1204b1f915 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -24,8 +24,9 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (always 4), * and writes into the supplied macro-op vector. */ - int8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, MacroOp& output) const override; + uint8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const override; /** Returns a zero-indexed register tag for a system register encoding. * Returns -1 in the case that the system register has no mapping. */ diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 50d2992c83..ebde07837f 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -29,8 +29,9 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (0 if * failure), and writes into the supplied macro-op vector. */ - int8_t predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, MacroOp& output) const override; + uint8_t predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const override; /** Returns a zero-indexed register tag for a system register encoding. */ int32_t getSystemRegisterTag(uint16_t reg) const override; diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 141a5503bd..5fa77159b4 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -144,9 +144,9 @@ Architecture::~Architecture() { SVCRval_ = 0; } -int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const { +uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by Armv9.2-a if (instructionAddress & 0x3) { // Consume 1-byte and raise a misaligned PC exception diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 5150c31348..6b2f1a7aff 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -153,9 +153,9 @@ Architecture::~Architecture() { groupExecutionInfo_.clear(); } -int8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, - MacroOp& output) const { +uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, + MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by RISC-V // 2-byte when Compressed ISA is supported if (instructionAddress & constants_.alignMask) { diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 3899254c67..346bfc5f31 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -196,7 +196,7 @@ void FetchUnit::tick() { break; } - // Too few bytes remaining in buffer to continue. + // Too few bytes remaining in buffer to continue if (bufferedBytes_ == 0) { break; } diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index 8e8a73ad63..0df643ee9e 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -9,8 +9,8 @@ namespace simeng { class MockArchitecture : public arch::Architecture { public: MOCK_CONST_METHOD4(predecode, - int8_t(const void* ptr, uint8_t bytesAvailable, - uint64_t instructionAddress, MacroOp& output)); + uint8_t(const void* ptr, uint8_t bytesAvailable, + uint64_t instructionAddress, MacroOp& output)); MOCK_CONST_METHOD1(canRename, bool(Register reg)); MOCK_CONST_METHOD1(getSystemRegisterTag, int32_t(uint16_t reg)); MOCK_CONST_METHOD3(handleException, From f8527d799005028728f08314a2554c0b7b8a693a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 8 Feb 2024 15:37:52 +0000 Subject: [PATCH 079/115] Add comments to compressed tests --- src/lib/arch/riscv/Architecture.cc | 1 - src/lib/arch/riscv/InstructionMetadata.cc | 2 ++ .../riscv/instructions/compressed.cc | 29 ++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 6b2f1a7aff..b93b68704a 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -1,7 +1,6 @@ #include "simeng/arch/riscv/Architecture.hh" #include -#include #include #include #include diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 232eafb276..3878ce190e 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -852,6 +852,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; default: + // Unimplemented compressed instruction, raise exception + aliasNYI(); break; } } diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 8b9ff332c4..12a7be9cf3 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -8,6 +8,7 @@ namespace { using InstCompressed = RISCVRegressionTest; TEST_P(InstCompressed, lwsp) { + // Load word from mem[stack pointer + imm] initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0xDEADBEEF; @@ -29,6 +30,7 @@ TEST_P(InstCompressed, lwsp) { } TEST_P(InstCompressed, ldsp) { + // Load double word from mem[stack pointer + imm] initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0xDEADBEEF; @@ -50,7 +52,8 @@ TEST_P(InstCompressed, ldsp) { EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); } -TEST_P(InstCompressed, flwsp) { +TEST_P(InstCompressed, fldsp) { + // Load double precision float from mem[stack pointer + imm] initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 1.0; @@ -78,6 +81,7 @@ TEST_P(InstCompressed, flwsp) { } TEST_P(InstCompressed, swsp) { + // Store word at mem[stack pointer + imm] RUN_RISCV_COMP(R"( li t6, 0xAA c.swsp t6, 0(sp) @@ -93,6 +97,7 @@ TEST_P(InstCompressed, swsp) { } TEST_P(InstCompressed, sdsp) { + // Store double word at mem[stack pointer + imm] RUN_RISCV_COMP(R"( li t6, 0xAA c.sdsp t6, 0(sp) @@ -109,6 +114,7 @@ TEST_P(InstCompressed, sdsp) { } TEST_P(InstCompressed, fsdsp) { + // Store double precision float at mem[stack pointer + imm] RUN_RISCV_COMP(R"( li t6, 0xAA fmv.d.x f8, t6 @@ -127,6 +133,7 @@ TEST_P(InstCompressed, fsdsp) { } TEST_P(InstCompressed, lw) { + // Compressed load word initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0xDEADBEEF; @@ -147,6 +154,7 @@ TEST_P(InstCompressed, lw) { } TEST_P(InstCompressed, ld) { + // Compressed store word initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0xDEADBEEF; @@ -168,6 +176,7 @@ TEST_P(InstCompressed, ld) { } TEST_P(InstCompressed, fld) { + // Compressed load double precision float initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 1.0; @@ -193,6 +202,7 @@ TEST_P(InstCompressed, fld) { } TEST_P(InstCompressed, addi4spn) { + // Add immediate to stack pointer RUN_RISCV_COMP(R"( c.addi4spn x8, x2, 4 c.addi4spn x9, x2, 12 @@ -202,6 +212,7 @@ TEST_P(InstCompressed, addi4spn) { } TEST_P(InstCompressed, sw) { + // Compressed store word initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0x12345678; @@ -228,6 +239,7 @@ TEST_P(InstCompressed, sw) { } TEST_P(InstCompressed, sd) { + // Compressed store double word initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 0x12345678; @@ -254,6 +266,7 @@ TEST_P(InstCompressed, sd) { } TEST_P(InstCompressed, fsd) { + // Compressed store double precision float initialHeapData_.resize(32); double* heap = reinterpret_cast(initialHeapData_.data()); heap[0] = 1.0; @@ -291,6 +304,7 @@ TEST_P(InstCompressed, fsd) { } TEST_P(InstCompressed, j) { + // Compressed jump // Labels needed as LLVM eagerly uses compressed instructions e.g. addi -> // c.addi causing manual jump offsets to be confusing RUN_RISCV_COMP(R"( @@ -313,6 +327,7 @@ TEST_P(InstCompressed, j) { } TEST_P(InstCompressed, jalr) { + // Compressed jump to address in rs1, save pc+2 in link register RUN_RISCV_COMP(R"( li x8, 12 c.jalr x8 @@ -337,6 +352,7 @@ TEST_P(InstCompressed, jalr) { } TEST_P(InstCompressed, beqz) { + // Compressed branch if rs1 equal to zero RUN_RISCV_COMP(R"( addi x8, x8, 2 c.beqz x8, b1 @@ -358,6 +374,7 @@ TEST_P(InstCompressed, beqz) { } TEST_P(InstCompressed, bnez) { + // Compressed branch if rs1 not equal to zero RUN_RISCV_COMP(R"( addi x8, x8, 0 c.bnez x8, b1 @@ -377,6 +394,7 @@ TEST_P(InstCompressed, bnez) { } TEST_P(InstCompressed, li) { + // Compressed load immediate RUN_RISCV_COMP(R"( addi a5, a5, 12 c.li a5, 0 @@ -391,6 +409,8 @@ TEST_P(InstCompressed, li) { } TEST_P(InstCompressed, lui) { + // Compressed load immediate into bits 17-12, clear bottom 12 and sign extend + // high bits RUN_RISCV_COMP(R"( c.lui t3, 4 c.lui t4, 0xFFFFC @@ -400,6 +420,7 @@ TEST_P(InstCompressed, lui) { } TEST_P(InstCompressed, addi) { + // Compressed add immediate RUN_RISCV_COMP(R"( c.addi t3, 3 c.addi t4, 6 @@ -412,6 +433,7 @@ TEST_P(InstCompressed, addi) { } TEST_P(InstCompressed, addiw) { + // Compressed add immediate. Produces 32 bit result and sign extends RUN_RISCV_COMP(R"( addi t3, t3, 91 slli t3, t3, 28 @@ -424,6 +446,7 @@ TEST_P(InstCompressed, addiw) { } TEST_P(InstCompressed, addi16sp) { + // Add immediate (multiple of 16) to stack pointer RUN_RISCV_COMP(R"( mv x8, sp c.addi16sp x2, 16 @@ -556,6 +579,8 @@ TEST_P(InstCompressed, subw) { } TEST_P(InstCompressed, nop) { + // Ensure that a nop doesn't change the state of the processor + // Check initial architectural state RUN_RISCV_COMP(R"( li x8, 1234 )"); @@ -603,6 +628,7 @@ TEST_P(InstCompressed, nop) { c.nop )"); + // Ensure state hasn't changed except the number of ticks EXPECT_EQ(getGeneralRegister(0), 0); EXPECT_EQ(getGeneralRegister(1), 0); EXPECT_EQ(getGeneralRegister(2), 199840); @@ -639,6 +665,7 @@ TEST_P(InstCompressed, nop) { } TEST_P(InstCompressed, ebreak) { + // Currently not implemented so ensure this produces an exception std::stringstream buffer; std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to buffer From 7ce768cea7d33922aa8fc8eb0fc591eabf49d351 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 8 Feb 2024 16:11:29 +0000 Subject: [PATCH 080/115] Cleanup --- src/include/simeng/arch/riscv/ArchInfo.hh | 1 + src/include/simeng/arch/riscv/Architecture.hh | 3 --- src/lib/arch/riscv/Architecture.cc | 2 -- test/regression/riscv/instructions/compressed.cc | 3 ++- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index 25c22e7ead..fdb66f6879 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -19,6 +19,7 @@ typedef enum riscv_sysreg { } riscv_sysreg; +// A struct of RISC-V specific constants struct constantsPool { const uint8_t alignMask = 0x3; const uint8_t alignMaskCompressed = 0x1; diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index ebde07837f..cce834f6eb 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -54,9 +54,6 @@ class Architecture : public arch::Architecture { void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const override; - /** Return a struct contains constants */ - archConstants getConstants() const; - private: /** Retrieve an executionInfo object for the requested instruction. If a * opcode-based override has been defined for the latency and/or diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index b93b68704a..a265647b19 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -309,8 +309,6 @@ void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, regFile->set(cycleSystemReg_, iterations); } -archConstants Architecture::getConstants() const { return constants_; } - } // namespace riscv } // namespace arch } // namespace simeng diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 12a7be9cf3..c45e09d41e 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -580,7 +580,7 @@ TEST_P(InstCompressed, subw) { TEST_P(InstCompressed, nop) { // Ensure that a nop doesn't change the state of the processor - // Check initial architectural state + // Load a register and check initial architectural state RUN_RISCV_COMP(R"( li x8, 1234 )"); @@ -620,6 +620,7 @@ TEST_P(InstCompressed, nop) { numTicks_ = 0; + // Run some no operations RUN_RISCV_COMP(R"( c.nop c.nop From 00bb37d97f3bfcc834488e99b5442b0de1a25303 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 13:56:20 +0000 Subject: [PATCH 081/115] Add min bytes getter and update fetch unit. Unit tests break --- src/include/simeng/arch/Architecture.hh | 3 +++ src/include/simeng/arch/aarch64/Architecture.hh | 3 +++ src/include/simeng/arch/riscv/Architecture.hh | 3 +++ src/lib/arch/aarch64/Architecture.cc | 4 ++++ src/lib/arch/riscv/Architecture.cc | 4 ++++ src/lib/pipeline/FetchUnit.cc | 2 +- test/unit/MockArchitecture.hh | 1 + 7 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 9a2d4c69bc..dd410fec20 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -87,6 +87,9 @@ class Architecture { /** Returns the maximum size of a valid instruction in bytes. */ virtual uint8_t getMaxInstructionSize() const = 0; + /** Returns the minimum size of a valid instruction in bytes. */ + virtual uint8_t getMinInstructionSize() const = 0; + /** Updates System registers of any system-based timers. */ virtual void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const = 0; diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 1204b1f915..8dc0049c92 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -46,6 +46,9 @@ class Architecture : public arch::Architecture { /** Returns the maximum size of a valid instruction in bytes. */ uint8_t getMaxInstructionSize() const override; + /** Returns the minimum size of a valid instruction in bytes. */ + uint8_t getMinInstructionSize() const override; + /** Returns the current vector length set by the provided configuration. */ uint64_t getVectorLength() const; diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index cce834f6eb..a24496e5a9 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -50,6 +50,9 @@ class Architecture : public arch::Architecture { /** Returns the maximum size of a valid instruction in bytes. */ uint8_t getMaxInstructionSize() const override; + /** Returns the minimum size of a valid instruction in bytes. */ + uint8_t getMinInstructionSize() const override; + /** Updates System registers of any system-based timers. */ void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const override; diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 5fa77159b4..db97c64124 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -1,3 +1,5 @@ +#include "simeng/arch/aarch64/Architecture.hh" + #include #include @@ -263,6 +265,8 @@ ProcessStateChange Architecture::getInitialState() const { uint8_t Architecture::getMaxInstructionSize() const { return 4; } +uint8_t Architecture::getMinInstructionSize() const { return 4; } + uint64_t Architecture::getVectorLength() const { return VL_; } uint64_t Architecture::getStreamingVectorLength() const { return SVL_; } diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index a265647b19..9f2fbea909 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -304,6 +304,10 @@ ProcessStateChange Architecture::getInitialState() const { uint8_t Architecture::getMaxInstructionSize() const { return 4; } +uint8_t Architecture::getMinInstructionSize() const { + return constants_.bytesLimit; +} + void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const { regFile->set(cycleSystemReg_, iterations); diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 346bfc5f31..324a03bc40 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -110,7 +110,7 @@ void FetchUnit::tick() { // Potentially a redundant check considering the above // Check we have enough data to begin decoding - if (bufferedBytes_ < isa_.getMaxInstructionSize()) return; + if (bufferedBytes_ < isa_.getMinInstructionSize()) return; auto outputSlots = output_.getTailSlots(); diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index 0df643ee9e..8b72a3c7cd 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -19,6 +19,7 @@ class MockArchitecture : public arch::Architecture { const Core& core, MemoryInterface& memory)); MOCK_CONST_METHOD0(getInitialState, arch::ProcessStateChange()); MOCK_CONST_METHOD0(getMaxInstructionSize, uint8_t()); + MOCK_CONST_METHOD0(getMinInstructionSize, uint8_t()); MOCK_CONST_METHOD2(updateSystemTimerRegisters, void(RegisterFileSet* regFile, const uint64_t iterations)); }; From de12b368188fd057954ac348fe8cc9e634e4e8aa Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 15:04:38 +0000 Subject: [PATCH 082/115] Address PR comments --- src/include/simeng/arch/riscv/Instruction.hh | 4 ++-- src/lib/arch/riscv/Instruction_address.cc | 1 - test/regression/riscv/RISCVRegressionTest.hh | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index bce59ec027..b94fefcae0 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -177,7 +177,6 @@ class Instruction : public simeng::Instruction { * instruction can have. */ static const uint8_t MAX_DESTINATION_REGISTERS = 1; - private: /** A reference to the ISA instance this instruction belongs to. */ const Architecture& architecture_; @@ -198,7 +197,8 @@ class Instruction : public simeng::Instruction { * `sourceRegisters` entry. */ std::array operands; - /** Extracted value of current immediate from metadata */ + /** The immediate source operand for which there is only ever one. Remains 0 + * if unused. */ int64_t imm_ = 0; /** An array of generated output results. Each entry corresponds to a diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index b9223eabaa..066301434d 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -1,5 +1,4 @@ #include -#include #include "InstructionMetadata.hh" #include "simeng/arch/riscv/Instruction.hh" diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 47c7e18ddc..42357739af 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -71,7 +71,7 @@ inline std::string paramToString( * an illegal instruction exception instead of running into the heap. This * specifically targets the compressed extension allowing for the above macro to * ignore it, otherwise LLVM eagerly emits compressed instructions for - * non-compressed assembly*/ + * non-compressed assembly. */ #define RUN_RISCV_COMP(source) \ { \ std::string sourceWithTerminator = source; \ From e9d9ad8bd59d98228ae1e3bda17074b1c37d2009 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 17:41:38 +0000 Subject: [PATCH 083/115] Fix fetch unit tests --- test/unit/pipeline/FetchUnitTest.cc | 30 ++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index f404029640..82dbff4fc7 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -41,6 +41,7 @@ class PipelineFetchUnitTest : public testing::Test { protected: const uint8_t insnMaxSizeBytes = 4; + const uint8_t insnMinSizeBytes = 2; const uint8_t blockSize = 16; PipelineBuffer output; @@ -100,11 +101,12 @@ TEST_F(PipelineFetchUnitTest, TickStalled) { TEST_F(PipelineFetchUnitTest, FetchUnaligned) { MacroOp mOp = {uopPtr}; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - // Set PC to 14, so there will not be enough data to start decoding + // Set PC to 15, so there will not be enough data to start decoding EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); - fetchUnit.updatePC(14); + fetchUnit.updatePC(15); fetchUnit.tick(); // Expect a block starting at address 16 to be requested when we fetch again @@ -120,7 +122,8 @@ TEST_F(PipelineFetchUnitTest, FetchUnaligned) { .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(4); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(8); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(4); + EXPECT_CALL(isa, getMinInstructionSize()).Times(4); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(4); // Tick 4 times to process all 16 bytes of fetched data @@ -130,6 +133,7 @@ TEST_F(PipelineFetchUnitTest, FetchUnaligned) { // Tick a 5th time to ensure all buffered bytes have been used EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); } @@ -140,6 +144,7 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { const uint8_t pc = 16; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); MemoryAccessTarget target = {pc, blockSize}; EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); @@ -158,7 +163,8 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(4); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(8); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(4); + EXPECT_CALL(isa, getMinInstructionSize()).Times(4); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(4); // Tick 4 times to process all 16 bytes of fetched data @@ -169,6 +175,7 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(0); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); } @@ -176,6 +183,7 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { // Tests that halting functionality triggers correctly TEST_F(PipelineFetchUnitTest, halted) { ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); EXPECT_FALSE(fetchUnit.hasHalted()); fetchUnit.tick(); EXPECT_FALSE(fetchUnit.hasHalted()); @@ -190,6 +198,7 @@ TEST_F(PipelineFetchUnitTest, halted) { MemoryAccessTarget target = {1008, blockSize}; EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(memory, requestRead(target, _)).Times(1); fetchUnit.requestFromPC(); @@ -202,7 +211,8 @@ TEST_F(PipelineFetchUnitTest, halted) { .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(4); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(8); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(4); + EXPECT_CALL(isa, getMinInstructionSize()).Times(4); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(4); // Tick 4 times to process all 16 bytes of fetched data for (int i = 0; i < 4; i++) { @@ -217,9 +227,11 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { const uint8_t pc = 16; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); MemoryAccessTarget target = {pc, blockSize}; EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(memory, requestRead(target, _)).Times(1); // Request block from memory @@ -237,7 +249,8 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { // For first tick, process instruction as non-branch EXPECT_CALL(memory, clearCompletedReads()).Times(1); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); EXPECT_CALL(*uop, isBranch()).WillOnce(Return(false)); fetchUnit.tick(); @@ -246,7 +259,8 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { // & a new memory block is requested EXPECT_CALL(memory, getCompletedReads()).Times(0); EXPECT_CALL(memory, clearCompletedReads()).Times(1); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); EXPECT_CALL(*uop, isBranch()).WillOnce(Return(true)); BranchType bType = BranchType::Unconditional; @@ -261,6 +275,7 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(0); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); @@ -268,6 +283,7 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { // (pred.target) target = {pred.target, blockSize}; EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(0); EXPECT_CALL(memory, requestRead(target, _)).Times(1); fetchUnit.requestFromPC(); } From b9dadd640d2b4ce617f043c41cb57318a3dbcafb Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 17:43:47 +0000 Subject: [PATCH 084/115] Change imm_ name to sourceImm --- src/include/simeng/arch/riscv/ArchInfo.hh | 3 +- src/include/simeng/arch/riscv/Instruction.hh | 2 +- src/lib/arch/riscv/ExceptionHandler.cc | 1 + src/lib/arch/riscv/Instruction_address.cc | 4 +- src/lib/arch/riscv/Instruction_decode.cc | 4 +- src/lib/arch/riscv/Instruction_execute.cc | 67 ++++++++++---------- src/lib/pipeline/FetchUnit.cc | 1 - 7 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index fdb66f6879..23a6e06d29 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -19,7 +19,8 @@ typedef enum riscv_sysreg { } riscv_sysreg; -// A struct of RISC-V specific constants +// TODO potentially convert to namespace +// A struct of RISC-V specific constants struct constantsPool { const uint8_t alignMask = 0x3; const uint8_t alignMaskCompressed = 0x1; diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index b94fefcae0..9859ed0afa 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -199,7 +199,7 @@ class Instruction : public simeng::Instruction { /** The immediate source operand for which there is only ever one. Remains 0 * if unused. */ - int64_t imm_ = 0; + int64_t sourceImm_ = 0; /** An array of generated output results. Each entry corresponds to a * `destinationRegisters` entry. */ diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index b6ebcbb924..2cc096fa80 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -913,6 +913,7 @@ void ExceptionHandler::printException(const Instruction& insn) const { << std::setfill('0') << std::setw(16) << insn.getInstructionAddress() << ": "; + // TODO only print 2 bytes if compressed auto& metadata = insn.getMetadata(); for (uint8_t byte : metadata.encoding) { std::cout << std::setfill('0') << std::setw(2) diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 066301434d..6d69c46136 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -36,13 +36,13 @@ span Instruction::generateAddresses() { assert(metadata.operands[1].type == RISCV_OP_MEM && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[0].get() + imm_; + address = operands[0].get() + sourceImm_; } else { assert((metadata.operands[1].type == RISCV_OP_MEM) && "metadata operand not of correct type during RISC-V address " "generation"); - address = operands[1].get() + imm_; + address = operands[1].get() + sourceImm_; } // Atomics diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index c31cfd4f0b..3a9168c796 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -205,14 +205,14 @@ void Instruction::decode() { else if (i > 0 && op.type == RISCV_OP_MEM) { // Memory operand sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); - imm_ = op.mem.disp; + sourceImm_ = op.mem.disp; sourceRegisterCount++; operandsPending++; } // First operand is never immediate else if (i > 0 && op.type == RISCV_OP_IMM) { - imm_ = op.imm; + sourceImm_ = op.imm; } } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 6946196c3b..8729d67e13 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -234,7 +234,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLI: { // SLLI rd,rs1,shamt const int64_t rs1 = operands[0].get(); - const int64_t shamt = imm_ & 63; // Only use lowest 6 bits + const int64_t shamt = sourceImm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 << shamt); results[0] = RegisterValue(out, 8); break; @@ -249,7 +249,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLLIW: { // SLLIW rd,rs1,shamt const int32_t rs1 = operands[0].get(); - const int32_t shamt = imm_ & 63; // Only use lowest 6 bits + const int32_t shamt = sourceImm_ & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 << shamt)); results[0] = RegisterValue(out, 8); break; @@ -264,7 +264,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLI: { // SRLI rd,rs1,shamt const uint64_t rs1 = operands[0].get(); - const uint64_t shamt = imm_ & 63; // Only use lowest 6 bits + const uint64_t shamt = sourceImm_ & 63; // Only use lowest 6 bits uint64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -279,7 +279,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRLIW: { // SRLIW rd,rs1,shamt const uint32_t rs1 = operands[0].get(); - const uint32_t shamt = imm_ & 63; // Only use lowest 6 bits + const uint32_t shamt = sourceImm_ & 63; // Only use lowest 6 bits uint64_t out = signExtendW(static_cast(rs1 >> shamt)); results[0] = RegisterValue(out, 8); break; @@ -294,7 +294,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAI: { // SRAI rd,rs1,shamt const int64_t rs1 = operands[0].get(); - const int64_t shamt = imm_ & 63; // Only use lowest 6 bits + const int64_t shamt = sourceImm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -309,7 +309,7 @@ void Instruction::execute() { } case Opcode::RISCV_SRAIW: { // SRAIW rd,rs1,shamt const int32_t rs1 = operands[0].get(); - const int32_t shamt = imm_ & 63; // Only use lowest 6 bits + const int32_t shamt = sourceImm_ & 63; // Only use lowest 6 bits int64_t out = static_cast(rs1 >> shamt); results[0] = RegisterValue(out, 8); break; @@ -330,15 +330,13 @@ void Instruction::execute() { } case Opcode::RISCV_ADDI: { // ADDI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t rs2 = imm_; - uint64_t out = static_cast(rs1 + rs2); + uint64_t out = static_cast(rs1 + sourceImm_); results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_ADDIW: { // ADDIW rd,rs1,imm const int32_t rs1 = operands[0].get(); - const int32_t sourceImm = imm_; - uint64_t out = signExtendW(rs1 + sourceImm); + uint64_t out = signExtendW(rs1 + sourceImm_); results[0] = RegisterValue(out, 8); break; } @@ -356,14 +354,15 @@ void Instruction::execute() { results[0] = RegisterValue(out, 8); break; } - case Opcode::RISCV_LUI: { // LUI rd,imm - uint64_t out = signExtendW(imm_ << 12); // Shift into upper 20 bits + case Opcode::RISCV_LUI: { // LUI rd,imm + uint64_t out = signExtendW(sourceImm_ << 12); // Shift into upper 20 bits results[0] = RegisterValue(out, 8); break; } case Opcode::RISCV_AUIPC: { // AUIPC rd,imm const int64_t pc = instructionAddress_; - const int64_t uimm = signExtendW(imm_ << 12); // Shift into upper 20 bits + const int64_t uimm = + signExtendW(sourceImm_ << 12); // Shift into upper 20 bits uint64_t out = static_cast(pc + uimm); results[0] = RegisterValue(out, 8); break; @@ -377,8 +376,7 @@ void Instruction::execute() { } case Opcode::RISCV_XORI: { // XORI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm_; - uint64_t out = static_cast(rs1 ^ sourceImm); + uint64_t out = static_cast(rs1 ^ sourceImm_); results[0] = RegisterValue(out, 8); break; } @@ -391,8 +389,7 @@ void Instruction::execute() { } case Opcode::RISCV_ORI: { // ORI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm_; - uint64_t out = static_cast(rs1 | sourceImm); + uint64_t out = static_cast(rs1 | sourceImm_); results[0] = RegisterValue(out, 8); break; } @@ -405,8 +402,7 @@ void Instruction::execute() { } case Opcode::RISCV_ANDI: { // ANDI rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = imm_; - uint64_t out = static_cast(rs1 & sourceImm); + uint64_t out = static_cast(rs1 & sourceImm_); results[0] = RegisterValue(out, 8); break; } @@ -432,8 +428,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLTI: { // SLTI rd,rs1,imm const int64_t rs1 = operands[0].get(); - const int64_t sourceImm = imm_; - if (rs1 < sourceImm) { + if (rs1 < sourceImm_) { results[0] = RegisterValue(static_cast(1), 8); } else { results[0] = RegisterValue(static_cast(0), 8); @@ -442,8 +437,7 @@ void Instruction::execute() { } case Opcode::RISCV_SLTIU: { // SLTIU rd,rs1,imm const uint64_t rs1 = operands[0].get(); - const uint64_t sourceImm = static_cast(imm_); - if (rs1 < sourceImm) { + if (rs1 < static_cast(sourceImm_)) { results[0] = RegisterValue(static_cast(1), 8); } else { results[0] = RegisterValue(static_cast(0), 8); @@ -454,7 +448,8 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 == rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.getInsnLength(); @@ -466,7 +461,8 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 != rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { // Increase by instruction size to account for compressed instructions @@ -479,7 +475,8 @@ void Instruction::execute() { const int64_t rs1 = operands[0].get(); const int64_t rs2 = operands[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.getInsnLength(); @@ -491,7 +488,8 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 < rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.getInsnLength(); @@ -503,7 +501,8 @@ void Instruction::execute() { const int64_t rs1 = operands[0].get(); const int64_t rs2 = operands[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.getInsnLength(); @@ -515,7 +514,8 @@ void Instruction::execute() { const uint64_t rs1 = operands[0].get(); const uint64_t rs2 = operands[1].get(); if (rs1 >= rs2) { - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; } else { branchAddress_ = instructionAddress_ + metadata.getInsnLength(); @@ -523,16 +523,17 @@ void Instruction::execute() { } break; } - case Opcode::RISCV_JAL: { // JAL rd,imm - branchAddress_ = instructionAddress_ + imm_; // Set LSB of result to 0 + case Opcode::RISCV_JAL: { // JAL rd,imm + branchAddress_ = + instructionAddress_ + sourceImm_; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.getInsnLength(), 8); break; } case Opcode::RISCV_JALR: { // JALR rd,rs1,imm - branchAddress_ = - (operands[0].get() + imm_) & ~1; // Set LSB of result to 0 + branchAddress_ = (operands[0].get() + sourceImm_) & + ~1; // Set LSB of result to 0 branchTaken_ = true; results[0] = RegisterValue(instructionAddress_ + metadata.getInsnLength(), 8); diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 324a03bc40..a75f401870 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -108,7 +108,6 @@ void FetchUnit::tick() { bufferOffset = 0; } - // Potentially a redundant check considering the above // Check we have enough data to begin decoding if (bufferedBytes_ < isa_.getMinInstructionSize()) return; From a2a674ec6c910059ae6a8a1c2a5dbf646142bbc2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 18:10:22 +0000 Subject: [PATCH 085/115] Update decode logic layout and add assertions --- src/lib/arch/riscv/Instruction_decode.cc | 65 +++++++++++++----------- src/lib/pipeline/FetchUnit.cc | 2 +- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 3a9168c796..149cd52548 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -182,37 +182,44 @@ void Instruction::decode() { */ } } - } + } else if (i > 0) { + // First operand is never of MEM or IMM type, every register operand after + // the first is a source register + if (op.type == RISCV_OP_REG) { + // Second or third register operand + sourceRegisters[sourceRegisterCount] = csRegToRegister(op.reg); - // For all instructions, every register operand after the first is a source - // register - else if (i > 0 && op.type == RISCV_OP_REG) { - // Second or third operand - sourceRegisters[sourceRegisterCount] = csRegToRegister(op.reg); + if (sourceRegisters[sourceRegisterCount] == + RegisterType::ZERO_REGISTER) { + // Catch zero register references and pre-complete those operands + operands[sourceRegisterCount] = RegisterValue(0, 8); + } else { + operandsPending++; + } - if (sourceRegisters[sourceRegisterCount] == RegisterType::ZERO_REGISTER) { - // Catch zero register references and pre-complete those operands - operands[sourceRegisterCount] = RegisterValue(0, 8); - } else { + sourceRegisterCount++; + } else if (op.type == RISCV_OP_MEM) { + // Memory operand + // Extract reg number from capstone object + sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); + sourceImm_ = op.mem.disp; + sourceRegisterCount++; operandsPending++; + } else if (op.type == RISCV_OP_IMM) { + // Immediate operand + sourceImm_ = op.imm; + } else { + // Something has gone wrong + assert( + false && + "[SimEng:Instruction_decode] Unexpected register type in non-first " + "operand position"); } - - sourceRegisterCount++; - } - - // First operand is never MEM type, only check after the first. If register - // contains memory address, extract reg number from capstone object - else if (i > 0 && op.type == RISCV_OP_MEM) { - // Memory operand - sourceRegisters[sourceRegisterCount] = csRegToRegister(op.mem.base); - sourceImm_ = op.mem.disp; - sourceRegisterCount++; - operandsPending++; - } - - // First operand is never immediate - else if (i > 0 && op.type == RISCV_OP_IMM) { - sourceImm_ = op.imm; + } else { + // Something has gone wrong + assert(false && + "[SimEng:Instruction_decode] Unexpected register type in first " + "operand position"); } } @@ -295,12 +302,12 @@ void Instruction::decode() { case Opcode::RISCV_BGE: case Opcode::RISCV_BGEU: branchType_ = BranchType::Conditional; - knownOffset_ = metadata.operands[2].imm; + knownOffset_ = sourceImm_; break; case Opcode::RISCV_JAL: case Opcode::RISCV_JALR: branchType_ = BranchType::Unconditional; - knownOffset_ = metadata.operands[1].imm; + knownOffset_ = sourceImm_; break; } } diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index a75f401870..fdf969a257 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -108,7 +108,7 @@ void FetchUnit::tick() { bufferOffset = 0; } - // Check we have enough data to begin decoding + // Check we have enough data to begin decoding as read may not have completed if (bufferedBytes_ < isa_.getMinInstructionSize()) return; auto outputSlots = output_.getTailSlots(); From 4b667ef9632800ac2d3b072c630ed4718c37d8c7 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Feb 2024 18:17:52 +0000 Subject: [PATCH 086/115] Remove extra newlines in fetch unit and update comment --- src/lib/pipeline/FetchUnit.cc | 3 --- test/regression/riscv/instructions/compressed.cc | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index fdf969a257..e87632ae30 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -98,7 +98,6 @@ void FetchUnit::tick() { blockSize_ - bufferOffset); bufferedBytes_ += blockSize_ - bufferOffset; - buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. bufferOffset = 0; @@ -112,7 +111,6 @@ void FetchUnit::tick() { if (bufferedBytes_ < isa_.getMinInstructionSize()) return; auto outputSlots = output_.getTailSlots(); - for (size_t slot = 0; slot < output_.getWidth(); slot++) { auto& macroOp = outputSlots[slot]; @@ -154,7 +152,6 @@ void FetchUnit::tick() { // loopBoundaryAddress_ has been fetched whilst filling the loop // buffer. Stop filling as loop body has been recorded and begin to // supply decode unit with instructions from the loop buffer - loopBufferState_ = LoopBufferState::SUPPLYING; bufferedBytes_ = 0; break; diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index c45e09d41e..10bff9717e 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -306,7 +306,8 @@ TEST_P(InstCompressed, fsd) { TEST_P(InstCompressed, j) { // Compressed jump // Labels needed as LLVM eagerly uses compressed instructions e.g. addi -> - // c.addi causing manual jump offsets to be confusing + // c.addi causing manual jump offsets to become seemingly misaligned with the + // values used in the tests RUN_RISCV_COMP(R"( c.j jump #c.j 0xc jumpa: From 2aa6801e14261e98defc2848d960d195896e93a2 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 11:41:58 +0000 Subject: [PATCH 087/115] Add comments to all tests and include JR and MV tests --- .../riscv/instructions/compressed.cc | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 10bff9717e..3b58609054 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -201,16 +201,6 @@ TEST_P(InstCompressed, fld) { EXPECT_EQ(getFPRegister(11), 123456); } -TEST_P(InstCompressed, addi4spn) { - // Add immediate to stack pointer - RUN_RISCV_COMP(R"( - c.addi4spn x8, x2, 4 - c.addi4spn x9, x2, 12 - )"); - EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer() + 4); - EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 12); -} - TEST_P(InstCompressed, sw) { // Compressed store word initialHeapData_.resize(16); @@ -327,6 +317,19 @@ TEST_P(InstCompressed, j) { EXPECT_EQ(getGeneralRegister(0), 0); } +TEST_P(InstCompressed, jr) { + // Compressed jump to address in register + RUN_RISCV_COMP(R"( + c.addi x9, 8 + c.jr x9 + c.addi x8, 4 + c.j end + c.addi x8, 5 + end: + )"); + EXPECT_EQ(getGeneralRegister(8), 5); +} + TEST_P(InstCompressed, jalr) { // Compressed jump to address in rs1, save pc+2 in link register RUN_RISCV_COMP(R"( @@ -457,7 +460,18 @@ TEST_P(InstCompressed, addi16sp) { EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 16); } +TEST_P(InstCompressed, addi4spn) { + // Add immediate to stack pointer + RUN_RISCV_COMP(R"( + c.addi4spn x8, x2, 4 + c.addi4spn x9, x2, 12 + )"); + EXPECT_EQ(getGeneralRegister(8), process_->getStackPointer() + 4); + EXPECT_EQ(getGeneralRegister(9), process_->getStackPointer() + 12); +} + TEST_P(InstCompressed, slli) { + // Compressed shift left logical by immediate. rs1 = rd RUN_RISCV_COMP(R"( addi t4, t4, 6 c.slli t4, 5 @@ -466,6 +480,7 @@ TEST_P(InstCompressed, slli) { } TEST_P(InstCompressed, srli) { + // Compressed shift right logical by immediate. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, -4 c.srli x8, 61 @@ -474,6 +489,7 @@ TEST_P(InstCompressed, srli) { } TEST_P(InstCompressed, srai) { + // Compressed shift right arithmetic by immediate. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, -4 add t0, t0, x8 @@ -486,6 +502,7 @@ TEST_P(InstCompressed, srai) { } TEST_P(InstCompressed, andi) { + // Compressed AND with sign extended immediate. rs1 = rd RUN_RISCV_COMP(R"( addi x9, x9, 3 addi t4, t4, 5 @@ -497,7 +514,19 @@ TEST_P(InstCompressed, andi) { EXPECT_EQ(getGeneralRegister(9), 1); } +TEST_P(InstCompressed, mv) { + // Compressed move + RUN_RISCV_COMP(R"( + addi x8, x8, 3 + addi x9, x9, 6 + c.mv x8, x9 + )"); + EXPECT_EQ(getGeneralRegister(8), 6u); + EXPECT_EQ(getGeneralRegister(9), 6u); +} + TEST_P(InstCompressed, add) { + // Compressed add. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, 3 addi x9, x9, 6 @@ -508,6 +537,7 @@ TEST_P(InstCompressed, add) { } TEST_P(InstCompressed, and) { + // Compressed AND. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, 3 addi x9, x9, 5 @@ -517,6 +547,7 @@ TEST_P(InstCompressed, and) { } TEST_P(InstCompressed, or) { + // Compressed OR. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, 3 addi x9, x9, 5 @@ -526,6 +557,7 @@ TEST_P(InstCompressed, or) { } TEST_P(InstCompressed, xor) { + // Compressed XOR. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, 3 addi x9, x9, 5 @@ -535,6 +567,7 @@ TEST_P(InstCompressed, xor) { } TEST_P(InstCompressed, sub) { + // Compressed subtract. rs1 = rd RUN_RISCV_COMP(R"( addi x8, x8, 3 addi x9, x9, 6 @@ -547,6 +580,8 @@ TEST_P(InstCompressed, sub) { } TEST_P(InstCompressed, addw) { + // Compressed add word. Adds rd and rs2 then sign extends lower 32 bits. rs1 = + // rd RUN_RISCV_COMP(R"( addi x9, x9, -7 addi x8, x8, 3 @@ -560,6 +595,8 @@ TEST_P(InstCompressed, addw) { } TEST_P(InstCompressed, subw) { + // Compressed subtract word. Subtracts rs2 from rd then sign extends lower 32 + // bits. rs1 = rd RUN_RISCV_COMP(R"( addi x9, x9, 3 addi x10, x10, 6 From db339bfe60e318d50d31b6234989fb48da14bf91 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 13:03:34 +0000 Subject: [PATCH 088/115] Use calloc in release mode and add free --- src/lib/arch/riscv/Architecture.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 9f2fbea909..a38b1615a3 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -205,14 +205,10 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { // No decoding present. Generate a fresh decoding, and add to cache -#ifndef NDEBUG - // Struct not initialised which can cause issues but can be slow + // Ensure cs_insn doesn't contain garbage data cs_insn* rawInsnPointer = (cs_insn*)calloc(1, sizeof(cs_insn)); cs_insn rawInsn = *rawInsnPointer; assert(rawInsn.size == 0 && "rawInsn not initialised correctly"); -#else - cs_insn rawInsn; -#endif cs_detail rawDetail; rawInsn.detail = &rawDetail; @@ -231,6 +227,8 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, auto metadata = success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding, rawInsn.size); + free(rawInsnPointer); + // Cache the metadata metadataCache.push_front(metadata); From e0cfbdadbf52d55abf7ef50e34d03abc72145b9e Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 13:12:41 +0000 Subject: [PATCH 089/115] Only print relevant bytes on exception --- src/lib/arch/riscv/ExceptionHandler.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index 2cc096fa80..c343f9f685 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -913,11 +913,13 @@ void ExceptionHandler::printException(const Instruction& insn) const { << std::setfill('0') << std::setw(16) << insn.getInstructionAddress() << ": "; - // TODO only print 2 bytes if compressed auto& metadata = insn.getMetadata(); - for (uint8_t byte : metadata.encoding) { + for (uint8_t byteIndex = 0; byteIndex < insn.getMetadata().getInsnLength(); + byteIndex++) { std::cout << std::setfill('0') << std::setw(2) - << static_cast(byte) << " "; + << static_cast( + insn.getMetadata().encoding[byteIndex]) + << " "; } std::cout << std::dec << " "; if (exception == InstructionException::EncodingUnallocated) { From 84eb25f009649eefa9ca3c38458af36d71dc729a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 17:02:14 +0000 Subject: [PATCH 090/115] Add assertions for reserved encodings --- src/lib/arch/riscv/InstructionMetadata.cc | 149 +++++++++++++++++++--- 1 file changed, 128 insertions(+), 21 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 3878ce190e..c69c3eb88e 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -482,8 +482,13 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { switch (insn.opcode) { case Opcode::RISCV_C_JR: // jalr x0, 0(rs1) - // trap if rs1 = zero - // C.JR Rs, _, _ -> JALR x0, Rs, 0 + // C.JR rs1, _, _ -> JALR x0, rs1, 0 + + // rs1=zero is reserved + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.JR has rs1=x0 which is " + "reserved"); + opcode = Opcode::RISCV_JALR; operands[0].type = RISCV_OP_REG; @@ -499,9 +504,14 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_MV: // add rd, x0, rs2 - // trap if rs2 = zero. rs2 == zero corresponds to C.JR - // rs2==zero and rd == zero are hints + // rs2 == zero and rd == zero are hints // C.MV rd, rs2, _ -> ADD rd, zero, rs2 + + // rs2 = zero corresponds to C.JR + assert((operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + "[SimEng:convertCompressedInstruction] C.MV has rs2=x0 which is " + "invalid"); + opcode = Opcode::RISCV_ADD; includeZeroRegisterPosOne(); @@ -510,8 +520,13 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { case Opcode::RISCV_C_LDSP: { // TODO valid for RV64 only. Make this check // ld rd, offset[8:3](x2) - // offset is immediate scaled by 8 - // trap if rd=zero + // offset is immediate scaled by 8. Capstone does scaling for us + + // rd = zero is reserved + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.LDSP has rd=x0 which is " + "reserved"); + opcode = Opcode::RISCV_LD; // Create operand formatted like LD instruction @@ -521,14 +536,24 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { } case Opcode::RISCV_C_ADDI4SPN: // addi rd ′ , x2, nzuimm[9:2] - // trap if nzuimm=zero + + // nzuimm = zero is reserved + assert((operands[2].type == RISCV_OP_IMM && operands[2].imm != 0) && + "[SimEng:convertCompressedInstruction] C.ADDI4SPN has nzuimm=0 " + "which is reserved"); + opcode = Opcode::RISCV_ADDI; // All operands correct break; case Opcode::RISCV_C_LI: // addi rd, x0, imm[5:0] - // trap if rd=zero // C.LI rd, imm, _ -> addi rd, zero, imm + + // rd = zero encodes hints + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.LI has rd=x0 which is " + "invalid"); + opcode = Opcode::RISCV_ADDI; includeZeroRegisterPosOne(); @@ -537,8 +562,13 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { case Opcode::RISCV_C_ADDI16SP: // Opcode shared with C.LUI but has Rd = x2 // addi x2, x2, nzimm[9:4] - // trap if nzimm=zero // C.ADDI16SP sp, imm, _ -> addi sp, sp, imm + + // nzimm = zero is reserved + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.ADDI16SP has nzimm=0 " + "which is reserved"); + opcode = Opcode::RISCV_ADDI; duplicateFirstOp(); @@ -547,14 +577,24 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { case Opcode::RISCV_C_SLLI: // slli rd, rd, shamt[5:0] // - // For RV32C, shamt[5] must be zero; the code points with shamt[5]=1 are + // "For RV32C, shamt[5] must be zero; the code points with shamt[5]=1 are // reserved for custom extensions. For RV32C and RV64C, the shift amount // must be non-zero; the code points with shamt=0 are HINTs. For all base // ISAs, the code points with rd=x0 are HINTs, except those with - // shamt[5]=1 in RV32C. - + // shamt[5]=1 in RV32C." - Spec page 107 + // // C.SLLI rd, shamt, _ -> slli rd, rd, shamt + // shamt = zero is reserved for hints + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.SLLI has shamt=0 " + "which is reserved for hints"); + + // rd = zero encodes hints + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.SLLI has rd=x0 which is " + "reserved for hints"); + opcode = Opcode::RISCV_SLLI; duplicateFirstOp(); @@ -581,13 +621,26 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { } case Opcode::RISCV_C_ADD: // add rd, rd, rs2 - // trap if rs2 = zero - // code points with rs2=x0 correspond + // + // "code points with rs2=x0 correspond // to the C.JALR and C.EBREAK // instructions. The code points with - // rs2̸=x0 and rd=x0 are HINTs. + // rs2̸=x0 and rd=x0 are HINTs." - Spec page 108 + // // C.ADD rd, rs2, _ -> add rd, rd, rs2 + // rs2 = zero corresponds to C.JALR and C.EBREAK + assert((operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 which is " + "invalid"); + + // rs2 = zero AND rd = zero are reserved for hints + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1 && + operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 and rd=x0 " + "which is " + "reserved for hints"); + opcode = Opcode::RISCV_ADD; duplicateFirstOp(); @@ -606,9 +659,18 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { } case Opcode::RISCV_C_ADDI: { // addi rd, rd, nzimm[5:0] - // trap if rd=zero and imm=zero // C.ADDI rd, imm, _ -> addi rd, rd, imm + // rd = zero encodes C.NOP + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.ADDI has rd=x0 which is " + "invalid"); + + // nzimm = zero is reserved for hints + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.ADDI has nzimm=0 " + "which is reserved for hints"); + opcode = Opcode::RISCV_ADDI; duplicateFirstOp(); @@ -651,12 +713,33 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_LUI: // lui rd, nzimm[17:12] - // trap if rd = x0/x2, imm = 0 + + // nzimm = zero is reserved + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.LUI has nzimm=0 " + "which is reserved"); + + // rd = zero is reserved for hints + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.LUI has rd=x0 which is " + "reserved for hints"); + + // rd = x2 encodes C.ADDI16SP + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 3) && + "[SimEng:convertCompressedInstruction] C.LUI has rd=x2 which is " + "invalid"); + opcode = Opcode::RISCV_LUI; // all operands correct break; case Opcode::RISCV_C_LWSP: { // lw rd, offset[7:2](x2) + + // rd = zero is reserved + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.LWSP has rd=x0 which is " + "reserved"); + opcode = Opcode::RISCV_LW; createMemOpPosOne(); @@ -696,8 +779,15 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { case Opcode::RISCV_C_ADDIW: // TODO rv64 ONLY, make check for this // addiw rd, rd, imm[5:0] - // trap if rd = zero // C.ADDIW rd, imm, _ -> addiw rd, rd, imm + + // "The immediate can be zero for C.ADDIW, where this corresponds to + // [pseudoinstruction] sext.w rd" - Spec page 106 + // rd = zero is reserved + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.ADDIW has rd=x0 which is " + "reserved"); + opcode = Opcode::RISCV_ADDIW; duplicateFirstOp(); @@ -719,17 +809,20 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { createMemOpPosOne(); break; - case Opcode::RISCV_C_SRLI: // srli rd ′ , rd ′ , shamt[5:0] // C.SRLI rd, imm, _ -> srli rd, rd, imm + // shamt = zero is reserved for hints + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.SRLI has shamt=0 " + "which is reserved for hints"); + opcode = Opcode::RISCV_SRLI; duplicateFirstOp(); break; - case Opcode::RISCV_C_ADDW: // TODO rv64 ONLY, make check for this // addw rd ′ , rd ′ , rs2 ′ @@ -758,9 +851,13 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_JALR: // jalr x1, 0(rs1) - // trap if rs1=zero // C.JALR rs1, _, _ -> jalr x1, rs1, 0 + // rs1=zero corresponds to C.EBREAK instruction + assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + "[SimEng:convertCompressedInstruction] C.JALR has rs1=x0 which is " + "invalid"); + opcode = Opcode::RISCV_JALR; operands[1] = operands[0]; @@ -786,6 +883,11 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // srai rd ′ , rd ′ , shamt[5:0] // C.SRAI rd, imm, _ -> srai rd, rd, imm + // shamt = zero is reserved for hints + assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && + "[SimEng:convertCompressedInstruction] C.SRAI has shamt=0 " + "which is reserved for hints"); + opcode = Opcode::RISCV_SRAI; duplicateFirstOp(); @@ -831,6 +933,10 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { case Opcode::RISCV_C_NOP: // nop // C.NOP _, _, _-> addi x0, x0, 0 + + // TODO imm != zero is reserved for hints. Capstone doesn't give this + // value so can't be checked + opcode = Opcode::RISCV_ADDI; // Duplicate implementation of nop pseudoinstruction @@ -847,6 +953,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_EBREAK: + // ebreak opcode = Opcode::RISCV_EBREAK; From e7f72e2bc652ef33a3cf56c27a77db7137a5ef2c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 17:07:17 +0000 Subject: [PATCH 091/115] Update TODO's --- src/lib/arch/riscv/InstructionMetadata.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index c69c3eb88e..ecc26b95fb 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -518,7 +518,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_LDSP: { - // TODO valid for RV64 only. Make this check + // TODO valid for RV64 only. Make this check once RV32 implemented // ld rd, offset[8:3](x2) // offset is immediate scaled by 8. Capstone does scaling for us @@ -601,7 +601,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_SDSP: { - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // sd rs2, offset[8:3](x2) opcode = Opcode::RISCV_SD; @@ -647,7 +647,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_LD: { - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // ld rd ′ , offset[7:3](rs1 ′) opcode = Opcode::RISCV_LD; @@ -686,7 +686,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_SD: { - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // sd rs2 ′ , offset[7:3](rs1 ′) opcode = Opcode::RISCV_SD; @@ -747,7 +747,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; } case Opcode::RISCV_C_FLDSP: - // TODO RV32DC/RV64DC-only + // TODO RV32DC/RV64DC-only once RV32 implemented // fld rd, offset[8:3](x2) opcode = Opcode::RISCV_FLD; @@ -777,7 +777,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_ADDIW: - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // addiw rd, rd, imm[5:0] // C.ADDIW rd, imm, _ -> addiw rd, rd, imm @@ -824,7 +824,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_ADDW: - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // addw rd ′ , rd ′ , rs2 ′ // C.ADDW rd, rs2, _ -> addw rd, rd, rs2 opcode = Opcode::RISCV_ADDW; @@ -894,7 +894,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_FSD: - // TODO rv64dc ONLY, make check for this + // TODO rv64dc ONLY, make check for this once RV32 implemented // fsd rs2 ′, offset[7:3](rs1 ′) opcode = Opcode::RISCV_FSD; @@ -903,7 +903,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_FLD: - // TODO rv64dc ONLY, make check for this + // TODO rv64dc ONLY, make check for this once RV32 implemented // fld rd ′, offset[7:3](rs1 ′) opcode = Opcode::RISCV_FLD; @@ -912,7 +912,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_FSDSP: - // TODO rv64dc ONLY, make check for this + // TODO rv64dc ONLY, make check for this once RV32 implemented // fsd rs2, offset[8:3](x2) opcode = Opcode::RISCV_FSD; @@ -921,7 +921,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { break; case Opcode::RISCV_C_SUBW: - // TODO rv64 ONLY, make check for this + // TODO rv64 ONLY, make check for this once RV32 implemented // subw rd ′ , rd ′ , rs2 ′ // C.SUBW rd, rs2, _ -> subw rd, rd, rs2 From 36d20c687a51ed44cf437cb20050d17282460e97 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 22:42:58 +0000 Subject: [PATCH 092/115] Remove arch constants struct --- configs/DEMO_RISCV.yaml | 1 + src/include/simeng/arch/riscv/ArchInfo.hh | 17 +++++----- src/include/simeng/arch/riscv/Architecture.hh | 16 ++++----- src/lib/arch/riscv/Architecture.cc | 34 ++++++++++++------- src/lib/config/ModelConfig.cc | 8 ++++- .../riscv/instructions/compressed.cc | 2 +- 6 files changed, 46 insertions(+), 32 deletions(-) diff --git a/configs/DEMO_RISCV.yaml b/configs/DEMO_RISCV.yaml index 5f3387ef1f..1439b85158 100644 --- a/configs/DEMO_RISCV.yaml +++ b/configs/DEMO_RISCV.yaml @@ -4,6 +4,7 @@ Core: ISA: rv64 + Compressed: True Simulation-Mode: outoforder Clock-Frequency-GHz: 2.5 Timer-Frequency-MHz: 200 diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index 23a6e06d29..75e5fcd678 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -19,16 +19,15 @@ typedef enum riscv_sysreg { } riscv_sysreg; -// TODO potentially convert to namespace // A struct of RISC-V specific constants -struct constantsPool { - const uint8_t alignMask = 0x3; - const uint8_t alignMaskCompressed = 0x1; - const uint8_t bytesLimit = 4; - const uint8_t bytesLimitCompressed = 2; - const uint8_t byteLength64 = 8; - const uint8_t byteLength32 = 4; -}; +namespace constantsPool { +const uint8_t alignMask = 0x3; +const uint8_t alignMaskCompressed = 0x1; +const uint8_t bytesLimit = 4; +const uint8_t bytesLimitCompressed = 2; +const uint8_t byteLength64 = 8; +const uint8_t byteLength32 = 4; +}; // namespace constantsPool /** A class to hold and generate riscv specific architecture configuration * options. */ diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index a24496e5a9..08a6884ed6 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -14,12 +14,6 @@ namespace simeng { namespace arch { namespace riscv { -struct archConstants { - uint8_t alignMask; - uint8_t bytesLimit; /* Minimum bytes the decoder needs to process */ - uint8_t regWidth; /* Register width in bytes */ -}; - /* A basic RISC-V implementation of the `Architecture` interface. */ class Architecture : public arch::Architecture { public: @@ -93,8 +87,14 @@ class Architecture : public arch::Architecture { /** System Register of Processor Cycle Counter. */ simeng::Register cycleSystemReg_; - /** A struct contains constants */ - archConstants constants_; + /** A mask used to determine if an address has the correct byte alignment */ + uint8_t alignMask; + + /** Register width in bytes */ + uint8_t regWidth = constantsPool::byteLength64; + + /** Minimum number of bytes that can represent an instruction */ + uint8_t minInsnLength; }; } // namespace riscv diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index a38b1615a3..14be263161 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -20,14 +20,24 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) // TODO set fcsr accordingly when Zicsr extension supported fesetround(FE_TONEAREST); - constantsPool constantsPool; - constants_.alignMask = constantsPool.alignMaskCompressed; - constants_.regWidth = constantsPool.byteLength64; - constants_.bytesLimit = constantsPool.bytesLimitCompressed; + cs_err n; - cs_err n = cs_open(CS_ARCH_RISCV, - static_cast(CS_MODE_RISCV64 | CS_MODE_RISCVC), - &capstoneHandle); + regWidth = constantsPool::byteLength64; + + if (config["Core"]["Compressed"].as()) { + alignMask = constantsPool::alignMaskCompressed; + minInsnLength = constantsPool::bytesLimitCompressed; + + n = cs_open(CS_ARCH_RISCV, + static_cast(CS_MODE_RISCV64 | CS_MODE_RISCVC), + &capstoneHandle); + } else { + alignMask = constantsPool::alignMask; + minInsnLength = constantsPool::bytesLimit; + + n = cs_open(CS_ARCH_RISCV, static_cast(CS_MODE_RISCV64), + &capstoneHandle); + } if (n != CS_ERR_OK) { std::cerr << "[SimEng:Architecture] Could not create capstone handle due " @@ -156,8 +166,8 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by RISC-V - // 2-byte when Compressed ISA is supported - if (instructionAddress & constants_.alignMask) { + // 2-byte when Compressed extension is supported + if (instructionAddress & alignMask) { // Consume 1-byte and raise a misaligned PC exception auto metadata = InstructionMetadata((uint8_t*)ptr, 1); metadataCache.emplace_front(metadata); @@ -170,7 +180,7 @@ uint8_t Architecture::predecode(const void* ptr, uint8_t bytesAvailable, return 1; } - assert(bytesAvailable >= constants_.bytesLimit && + assert(bytesAvailable >= minInsnLength && "Fewer than bytes limit supplied to RISC-V decoder"); // Get the first byte @@ -302,9 +312,7 @@ ProcessStateChange Architecture::getInitialState() const { uint8_t Architecture::getMaxInstructionSize() const { return 4; } -uint8_t Architecture::getMinInstructionSize() const { - return constants_.bytesLimit; -} +uint8_t Architecture::getMinInstructionSize() const { return minInsnLength; } void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const { diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index 697c14c7c4..807aa68e3a 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -250,12 +250,18 @@ void ModelConfig::setExpectations(bool isDefault) { // Set isa_ if (ISA == "AArch64") { isa_ = ISA::AArch64; - } else if ("rv64") { + } else if (ISA == "rv64") { isa_ = ISA::RV64; } } createGroupMapping(); + if (isa_ == ISA::RV64) { + expectations_["Core"].addChild( + ExpectationNode::createExpectation(true, "Compressed")); + expectations_["Core"]["Compressed"].setValueSet(std::vector{false, true}); + } + expectations_["Core"].addChild( ExpectationNode::createExpectation("emulation", "Simulation-Mode")); diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 3b58609054..16801adba4 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -719,7 +719,7 @@ TEST_P(InstCompressed, ebreak) { "not-yet-implemented exception")); EXPECT_THAT(buffer.str(), HasSubstr("[SimEng:ExceptionHandler] 0x0000000000000000: 02 " - "90 00 00 c.ebreak ")); + "90 c.ebreak")); buffer.str(std::string()); } From e795794cedb01a69ff4366b878996eef0a1d9d23 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 12 Feb 2024 22:52:22 +0000 Subject: [PATCH 093/115] Docs update --- docs/sphinx/developer/arch/supported/riscv.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/developer/arch/supported/riscv.rst b/docs/sphinx/developer/arch/supported/riscv.rst index 7049093d68..172332c498 100644 --- a/docs/sphinx/developer/arch/supported/riscv.rst +++ b/docs/sphinx/developer/arch/supported/riscv.rst @@ -1,7 +1,7 @@ RISCV ======= -SimEng provides an almost complete implementation of the rv64imafd architecture, as well as being capable of handling some supervisor call (syscall) exceptions via basic system call emulation. This is sufficient to run many simple single threaded programs that have been statically compiled with the standard library. +SimEng provides an almost complete implementation of the rv64imafdc architecture, as well as being capable of handling some supervisor call (syscall) exceptions via basic system call emulation. This is sufficient to run many simple single threaded programs that have been statically compiled with the standard library. .. contents:: Contents @@ -57,6 +57,8 @@ Adding execution behaviour The process for adding a new instruction is very similar to that of :ref:`AArch64 `, by adding a new, uniquely identified entry to ``src/lib/arch/riscv/Instruction_execute.cc``. +Compressed instructions are treated in the same way as pseudoinstructions. By design they can be expanded to full instructions from the base and floating point extensions. A new case should be added to the switch statement in ``InstructionMetadata`` to perform the relevant adjustment to the metadata. The instruction can then be allowed to flow through the pipeline - no new execute case is necessary. + Zero registers ************** From b5ed8f5f2c6bbd3dec23a4586a0098b7f50d3da1 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 13 Feb 2024 13:19:48 +0000 Subject: [PATCH 094/115] Add fetch unit tests and allow continuation with 2 bytes in buffer --- src/include/simeng/pipeline/FetchUnit.hh | 7 + src/lib/pipeline/FetchUnit.cc | 52 +++-- test/unit/pipeline/FetchUnitTest.cc | 239 ++++++++++++++++++++++- 3 files changed, 283 insertions(+), 15 deletions(-) diff --git a/src/include/simeng/pipeline/FetchUnit.hh b/src/include/simeng/pipeline/FetchUnit.hh index c09f830654..accbf823e4 100644 --- a/src/include/simeng/pipeline/FetchUnit.hh +++ b/src/include/simeng/pipeline/FetchUnit.hh @@ -116,6 +116,13 @@ class FetchUnit { /** The amount of data currently in the fetch buffer. */ uint8_t bufferedBytes_ = 0; + + /** Let the following PipelineFetchUnitTest derived classes be a friend of + * this class to allow proper testing of 'tick' function. */ + friend class PipelineFetchUnitTest_invalidHalfWordAtEndOfBuffer_Test; + friend class PipelineFetchUnitTest_compressedInstructionAtEndOfBuffer_Test; + friend class PipelineFetchUnitTest_validCompressed_ReadsDontComplete_Test; + friend class PipelineFetchUnitTest_invalidHalfWord_readsDontComplete_Test; }; } // namespace pipeline diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index e87632ae30..a57600319b 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -25,6 +25,9 @@ FetchUnit::FetchUnit(PipelineBuffer& output, FetchUnit::~FetchUnit() { delete[] fetchBuffer_; } void FetchUnit::tick() { + std::cout << "tick pc=" << pc_ << " bufferedBytes=" << (int)bufferedBytes_ + << std::endl; + if (output_.isStalled()) { return; } @@ -62,6 +65,8 @@ void FetchUnit::tick() { // Check if more instruction data is required if (bufferedBytes_ < isa_.getMaxInstructionSize()) { + std::cout << "more data required" << std::endl; + // Calculate the address of the next fetch block uint64_t blockAddress; if (bufferedBytes_ > 0) { @@ -75,6 +80,8 @@ void FetchUnit::tick() { bufferOffset = pc_ - blockAddress; } + std::cout << "get completed read" << std::endl; + // Find fetched memory that matches the desired block const auto& fetched = instructionMemory_.getCompletedReads(); @@ -84,29 +91,45 @@ void FetchUnit::tick() { break; } } - if (fetchIndex == fetched.size()) { + if (fetchIndex == fetched.size() && + bufferedBytes_ < isa_.getMinInstructionSize()) { + std::cout << "need to wait" << std::endl; + // Need to wait for fetched instructions return; - } + } else if (fetchIndex == fetched.size()) { + std::cout << "new case" << std::endl; - // TODO: Handle memory faults - assert(fetched[fetchIndex].data && "Memory read failed"); - const uint8_t* fetchData = fetched[fetchIndex].data.getAsVector(); + // There is minimal data already in the buffer which may be predecodable + // and no new data has been supplied - // Copy fetched data to fetch buffer after existing data - std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, - blockSize_ - bufferOffset); + // Do nothing and allow continuation + } else { + std::cout << "Move data into fetch buffer" << std::endl; - bufferedBytes_ += blockSize_ - bufferOffset; - buffer = fetchBuffer_; - // Decoding should start from the beginning of the fetchBuffer_. - bufferOffset = 0; + // Data has been successfully read, move into fetch buffer + // TODO: Handle memory faults + assert(fetched[fetchIndex].data && "Memory read failed"); + const uint8_t* fetchData = + fetched[fetchIndex].data.getAsVector(); + + // Copy fetched data to fetch buffer after existing data + std::memcpy(fetchBuffer_ + bufferedBytes_, fetchData + bufferOffset, + blockSize_ - bufferOffset); + + bufferedBytes_ += blockSize_ - bufferOffset; + buffer = fetchBuffer_; + // Decoding should start from the beginning of the fetchBuffer_. + bufferOffset = 0; + } } else { // There is already enough data in the fetch buffer, so use that buffer = fetchBuffer_; bufferOffset = 0; } + std::cout << "get min size" << std::endl; + // Check we have enough data to begin decoding as read may not have completed if (bufferedBytes_ < isa_.getMinInstructionSize()) return; @@ -114,6 +137,8 @@ void FetchUnit::tick() { for (size_t slot = 0; slot < output_.getWidth(); slot++) { auto& macroOp = outputSlots[slot]; + std::cout << "predecode" << std::endl; + auto bytesRead = isa_.predecode(buffer + bufferOffset, bufferedBytes_, pc_, macroOp); @@ -204,6 +229,9 @@ void FetchUnit::tick() { } instructionMemory_.clearCompletedReads(); + + std::cout << "end of tick, bufferedBytes=" << (int)bufferedBytes_ + << " pc=" << pc_ << std::endl; } void FetchUnit::registerLoopBoundary(uint64_t branchAddress) { diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 82dbff4fc7..c11c3bf85a 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -133,7 +133,7 @@ TEST_F(PipelineFetchUnitTest, FetchUnaligned) { // Tick a 5th time to ensure all buffered bytes have been used EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(0); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); } @@ -175,7 +175,7 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(0); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(0); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); } @@ -275,7 +275,7 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(memory, clearCompletedReads()).Times(0); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(0); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); fetchUnit.tick(); @@ -453,5 +453,238 @@ TEST_F(PipelineFetchUnitTest, idleLoopBufferDueToNotTakenBoundary) { EXPECT_EQ(output.getTailSlots()[0], mOp2); } +// Tests that a compressed instruction held at the end of the fetch buffer is +// allowed to be predecoded in the same cycle as being fetched +TEST_F(PipelineFetchUnitTest, compressedInstructionAtEndOfBuffer) { + ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain valid compressed instruction so predecode returns + // 2 bytes read + MacroOp mOp = {uopPtr}; + ON_CALL(isa, predecode(_, 2, 0xE, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(2))); + + // Fetch the data, only 2 bytes will be copied to fetch buffer. Should allow + // continuation to predecode + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Set PC to 14, buffered bytes = 0 + fetchUnit.updatePC(14); + // Tick. Fetch data and predecode + fetchUnit.tick(); + + // Buffer should now be empty as all bytes predecoded + EXPECT_EQ(fetchUnit.bufferedBytes_, 0); + + // Expect a block starting at address 16 to be requested when we fetch again + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, requestRead(Field(&MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + // Tick again, expecting that decoding will now resume + MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; + span nextBlock = {&nextBlockValue, 1}; + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); + ON_CALL(isa, predecode(_, _, _, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); + + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + // Completed reads called again as more data is requested + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + // Output of width 1 so only 1 call to predecode + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + fetchUnit.tick(); + + // Initially 0 bytes, 16 bytes added, 4 bytes predecoded leaving 12 bytes left + EXPECT_EQ(fetchUnit.bufferedBytes_, 12); +} + +// Test that invalid half byte held at the end of the buffer is not successfully +// predecoded and that more data is fetched subsequently allowing progression +TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { + ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + MacroOp mOp = {uopPtr}; + ON_CALL(isa, predecode(_, 2, 0xE, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + + // getMaxInstructionSize called for second time in assertion + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Set PC to 14, buffered bytes = 0 + fetchUnit.updatePC(14); + // Tick + fetchUnit.tick(); + + // No data consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + + // Expect that memory is requested even though there is data in the buffer as + // bufferedBytes < maxInstructionSize + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, requestRead(Field(&MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + // Tick again expecting buffer to be filled and a word is predecoded + MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; + span nextBlock = {&nextBlockValue, 1}; + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); + ON_CALL(isa, predecode(_, _, _, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); + + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + fetchUnit.tick(); + + // Initially 2 bytes, 16 bytes added, 4 bytes predecoded leaving 14 bytes left + EXPECT_EQ(fetchUnit.bufferedBytes_, 14); +} + +// Ensure progression with valid 2 bytes at end of buffer when next read doesn't +// complete +TEST_F(PipelineFetchUnitTest, validCompressed_ReadsDontComplete) { + ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain valid 6 bytes so predecode returns 4 bytes read on + // first tick + MacroOp mOp = {uopPtr}; + ON_CALL(isa, predecode(_, 6, 0xA, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); + + // Fetch the data, only last 6 bytes from block. Should allow continuation to + // predecode + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Set PC to 10, buffered bytes = 0 + fetchUnit.updatePC(10); + // Tick and predecode 4 bytes + fetchUnit.tick(); + + // Ensure 4 bytes consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + EXPECT_EQ(fetchUnit.pc_, 14); + + // Expect that memory is requested even though there is data in the buffer as + // bufferedBytes < maxInstructionSize + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, requestRead(Field(&MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + EXPECT_EQ(fetchUnit.pc_, 14); + + // Memory doesn't complete reads in next cycle but buffered bytes should be + // predecoded + ON_CALL(memory, getCompletedReads()) + .WillByDefault(Return(span{nullptr, 0})); + ON_CALL(isa, predecode(_, 2, 0xE, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(2))); + + // Path through fetch as follows: + // More data required as bufferedBytes_ < maxInsnSize so getCompletedReads + // Doesn't complete so buffer doesn't get added to + // Buffer still has some valid data so predecode should be called + + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(2); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Tick + fetchUnit.tick(); + + // Ensure 2 bytes are consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 0); + EXPECT_EQ(fetchUnit.pc_, 16); +} + +// If invalid 2 bytes and no load then repeated calls to +// predecode +// Should there be a way to prevent repeated predecode of the same invalid byte + +// TODO is this correct/desired behaviour???? +// Test that invalid half byte held at the end of the buffer is not successfully +// predecoded and should be retried when reads don't complete +TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { + ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + MacroOp mOp = {uopPtr}; + ON_CALL(isa, predecode(_, 2, 0xE, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + + // getMaxInstructionSize called for second time in assertion + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Set PC to 14, buffered bytes = 0 + fetchUnit.updatePC(14); + // Tick + fetchUnit.tick(); + + // No data consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + EXPECT_EQ(fetchUnit.pc_, 14); + + // Expect that memory is requested even though there is data in the buffer as + // bufferedBytes < maxInstructionSize + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, requestRead(Field(&MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + EXPECT_EQ(fetchUnit.pc_, 14); + + // Memory doesn't complete reads in next cycle but buffered bytes should + // attempt to be predecoded + ON_CALL(memory, getCompletedReads()) + .WillByDefault(Return(span{nullptr, 0})); + // Predecode still returns no bytes read + ON_CALL(isa, predecode(_, 2, 0xE, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + + // getMaxInsnSize called again in assertion + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(2); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Tick + fetchUnit.tick(); + + // Ensure 2 bytes are consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + EXPECT_EQ(fetchUnit.pc_, 14); +} + } // namespace pipeline } // namespace simeng From 7e8559018f6625ffe79e0001ef5d72aa03251e00 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 13 Feb 2024 17:41:58 +0000 Subject: [PATCH 095/115] Remove prints from fetch unit --- src/lib/pipeline/FetchUnit.cc | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 8806ad430a..466da11332 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -25,9 +25,6 @@ FetchUnit::FetchUnit(PipelineBuffer& output, FetchUnit::~FetchUnit() { delete[] fetchBuffer_; } void FetchUnit::tick() { - std::cout << "tick pc=" << pc_ << " bufferedBytes=" << (int)bufferedBytes_ - << std::endl; - if (output_.isStalled()) { return; } @@ -64,8 +61,6 @@ void FetchUnit::tick() { // Check if more instruction data is required if (bufferedBytes_ < isa_.getMaxInstructionSize()) { - std::cout << "more data required" << std::endl; - // Calculate the address of the next fetch block uint64_t blockAddress; if (bufferedBytes_ > 0) { @@ -79,8 +74,6 @@ void FetchUnit::tick() { bufferOffset = pc_ - blockAddress; } - std::cout << "get completed read" << std::endl; - // Find fetched memory that matches the desired block const auto& fetched = instructionMemory_.getCompletedReads(); @@ -92,20 +85,14 @@ void FetchUnit::tick() { } if (fetchIndex == fetched.size() && bufferedBytes_ < isa_.getMinInstructionSize()) { - std::cout << "need to wait" << std::endl; - // Need to wait for fetched instructions return; } else if (fetchIndex == fetched.size()) { - std::cout << "new case" << std::endl; - // There is minimal data already in the buffer which may be predecodable // and no new data has been supplied // Do nothing and allow continuation } else { - std::cout << "Move data into fetch buffer" << std::endl; - // Data has been successfully read, move into fetch buffer // TODO: Handle memory faults assert(fetched[fetchIndex].data && "Memory read failed"); @@ -127,8 +114,6 @@ void FetchUnit::tick() { bufferOffset = 0; } - std::cout << "get min size" << std::endl; - // Check we have enough data to begin decoding as read may not have completed if (bufferedBytes_ < isa_.getMinInstructionSize()) return; @@ -136,8 +121,6 @@ void FetchUnit::tick() { for (size_t slot = 0; slot < output_.getWidth(); slot++) { auto& macroOp = outputSlots[slot]; - std::cout << "predecode" << std::endl; - auto bytesRead = isa_.predecode(buffer + bufferOffset, bufferedBytes_, pc_, macroOp); @@ -228,9 +211,6 @@ void FetchUnit::tick() { } instructionMemory_.clearCompletedReads(); - - std::cout << "end of tick, bufferedBytes=" << (int)bufferedBytes_ - << " pc=" << pc_ << std::endl; } void FetchUnit::registerLoopBoundary(uint64_t branchAddress) { From 5e2a8b247f4d9616f52153005428cc231766fc66 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 13 Feb 2024 17:53:46 +0000 Subject: [PATCH 096/115] Remove query comments --- test/unit/pipeline/FetchUnitTest.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index c11c3bf85a..3769d90c88 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -622,11 +622,6 @@ TEST_F(PipelineFetchUnitTest, validCompressed_ReadsDontComplete) { EXPECT_EQ(fetchUnit.pc_, 16); } -// If invalid 2 bytes and no load then repeated calls to -// predecode -// Should there be a way to prevent repeated predecode of the same invalid byte - -// TODO is this correct/desired behaviour???? // Test that invalid half byte held at the end of the buffer is not successfully // predecoded and should be retried when reads don't complete TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { From 78aaa94bbaa5b9a8e6ef255524a6b67cccc1241d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 18:12:47 +0000 Subject: [PATCH 097/115] Comment cleanup --- src/lib/arch/riscv/InstructionMetadata.cc | 80 +++++++++++--------- test/regression/riscv/RISCVRegressionTest.cc | 13 +--- test/regression/riscv/RISCVRegressionTest.hh | 34 ++++----- 3 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index ecc26b95fb..5c4ad3af74 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -64,10 +64,10 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // ADDI _, _, _-> ADDI x0, x0, 0 // reg set to 1 to reflect capstones 1 indexed output operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_REG; - operands[1].reg = 1; + operands[1].reg = RISCV_REG_ZERO; operands[2].type = RISCV_OP_IMM; operands[2].imm = 0; @@ -145,7 +145,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // sltz Rd, Rs is pseudo of SLT Rd, Rs, x0 // SLT Rd, Rs, _ -> SLT Rd, Rs, x0 operands[2].type = RISCV_OP_REG; - operands[2].reg = 1; + operands[2].reg = RISCV_REG_ZERO; operandCount = 3; } else if (operandCount == 2 && strcmp(mnemonic, "sgtz") == 0) { @@ -160,7 +160,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // ret is pseudo of JALR x0, x1, 0 // JALR _, _, _ -> JALR x0, x1, 0 operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_REG; operands[1].reg = 2; @@ -173,7 +173,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // jr Rs is pseudo of JALR x0, Rs, 0 // JALR Rs, _, _ -> JALR x0, Rs, 0 operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1] = insn.detail->riscv.operands[0]; @@ -211,7 +211,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // j offset is pseudo of JAL x0, offset // JAL offset, _ -> JAL x0, offset operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_IMM; operands[1].imm = insn.detail->riscv.operands[0].imm; @@ -267,10 +267,10 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // flags) CSRRS Rs, _, _ -> CSRRS Rs, fflags, zero operands[1].type = RISCV_OP_IMM; // TODO needs to become reg when Capstone updated - operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + operands[1].imm = RISCV_SYSREG_FFLAGS; // fflags address operands[2].type = RISCV_OP_REG; - operands[2].reg = 1; + operands[2].reg = RISCV_REG_ZERO; operandCount = 3; } else if (strcmp(mnemonic, "rdinstret") == 0) { @@ -290,10 +290,10 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // CSRRS Rs, _, _ -> CSRRS Rs, frm, zero operands[1].type = RISCV_OP_IMM; // TODO needs to become reg when Capstone updated - operands[1].reg = RISCV_SYSREG_FRM; // frm address + operands[1].imm = RISCV_SYSREG_FRM; // frm address operands[2].type = RISCV_OP_REG; - operands[2].reg = 1; + operands[2].reg = RISCV_REG_ZERO; operandCount = 3; } @@ -307,11 +307,11 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[2] = operands[0]; operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_IMM; // TODO needs to become reg when Capstone updated - operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + operands[1].imm = RISCV_SYSREG_FFLAGS; // fflags address operandCount = 3; } else if (operandCount == 2 && strcmp(mnemonic, "fsflags") == 0) { @@ -322,7 +322,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[1].type = RISCV_OP_IMM; // TODO needs to become reg when Capstone updated - operands[1].reg = RISCV_SYSREG_FFLAGS; // fflags address + operands[1].imm = RISCV_SYSREG_FFLAGS; // fflags address operandCount = 3; } else if (strcmp(mnemonic, "csrw") == 0) { @@ -338,11 +338,11 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[2] = operands[0]; operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_IMM; // TODO needs to become reg when Capstone updated - operands[1].reg = RISCV_SYSREG_FRM; // frm address + operands[1].imm = RISCV_SYSREG_FRM; // frm address operandCount = 3; } else if (operandCount == 2 && strcmp(mnemonic, "fsrm") == 0) { @@ -351,7 +351,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[2] = operands[1]; operands[1].type = RISCV_OP_IMM; - operands[1].reg = RISCV_SYSREG_FRM; + operands[1].imm = RISCV_SYSREG_FRM; operandCount = 3; } @@ -433,7 +433,7 @@ void InstructionMetadata::includeZeroRegisterPosOne() { operands[2] = operands[1]; operands[1].type = RISCV_OP_REG; - operands[1].reg = 1; + operands[1].reg = RISCV_REG_ZERO; operandCount = 3; } @@ -444,7 +444,7 @@ void InstructionMetadata::includeZeroRegisterPosZero() { operands[1] = operands[0]; operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operandCount = 3; } @@ -492,7 +492,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_JALR; operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1] = insn.detail->riscv.operands[0]; @@ -508,7 +508,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.MV rd, rs2, _ -> ADD rd, zero, rs2 // rs2 = zero corresponds to C.JR - assert((operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + assert((operands[1].type == RISCV_OP_REG && + operands[1].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.MV has rs2=x0 which is " "invalid"); @@ -523,7 +524,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // offset is immediate scaled by 8. Capstone does scaling for us // rd = zero is reserved - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.LDSP has rd=x0 which is " "reserved"); @@ -550,7 +552,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.LI rd, imm, _ -> addi rd, zero, imm // rd = zero encodes hints - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.LI has rd=x0 which is " "invalid"); @@ -591,7 +594,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { "which is reserved for hints"); // rd = zero encodes hints - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.SLLI has rd=x0 which is " "reserved for hints"); @@ -630,13 +634,16 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.ADD rd, rs2, _ -> add rd, rd, rs2 // rs2 = zero corresponds to C.JALR and C.EBREAK - assert((operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + assert((operands[1].type == RISCV_OP_REG && + operands[1].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 which is " "invalid"); // rs2 = zero AND rd = zero are reserved for hints - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1 && - operands[1].type == RISCV_OP_REG && operands[1].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO && + operands[1].type == RISCV_OP_REG && + operands[1].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 and rd=x0 " "which is " "reserved for hints"); @@ -662,7 +669,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.ADDI rd, imm, _ -> addi rd, rd, imm // rd = zero encodes C.NOP - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.ADDI has rd=x0 which is " "invalid"); @@ -720,7 +728,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { "which is reserved"); // rd = zero is reserved for hints - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.LUI has rd=x0 which is " "reserved for hints"); @@ -736,7 +745,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // lw rd, offset[7:2](x2) // rd = zero is reserved - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.LWSP has rd=x0 which is " "reserved"); @@ -771,7 +781,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { operands[1] = operands[0]; operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operandCount = 2; @@ -784,7 +794,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // "The immediate can be zero for C.ADDIW, where this corresponds to // [pseudoinstruction] sext.w rd" - Spec page 106 // rd = zero is reserved - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.ADDIW has rd=x0 which is " "reserved"); @@ -854,7 +865,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.JALR rs1, _, _ -> jalr x1, rs1, 0 // rs1=zero corresponds to C.EBREAK instruction - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "[SimEng:convertCompressedInstruction] C.JALR has rs1=x0 which is " "invalid"); @@ -941,10 +953,10 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // Duplicate implementation of nop pseudoinstruction operands[0].type = RISCV_OP_REG; - operands[0].reg = 1; + operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_REG; - operands[1].reg = 1; + operands[1].reg = RISCV_REG_ZERO; operands[2].type = RISCV_OP_IMM; operands[2].imm = 0; diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index a45876a9cd..ca15332180 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -5,22 +5,13 @@ using namespace simeng::arch::riscv; -void RISCVRegressionTest::run(const char* source) { +void RISCVRegressionTest::run(const char* source, const char* extensions) { // Initialise LLVM LLVMInitializeRISCVTargetInfo(); LLVMInitializeRISCVTargetMC(); LLVMInitializeRISCVAsmParser(); - RegressionTest::run(source, "riscv64", "+m,+a,+f,+d"); -} - -void RISCVRegressionTest::runCompressed(const char* source) { - // Initialise LLVM - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeRISCVAsmParser(); - - RegressionTest::run(source, "riscv64", "+m,+a,+f,+d,+c"); + RegressionTest::run(source, "riscv64", extensions); } void RISCVRegressionTest::generateConfig() const { diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index cb6b53c673..cdb9492691 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -57,27 +57,27 @@ inline std::string paramToString( * 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. */ -#define RUN_RISCV(source) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - run(sourceWithTerminator.c_str()); \ - } \ +#define RUN_RISCV(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), "+m,+a,+f,+d"); \ + } \ if (HasFatalFailure()) return /** A helper macro to run a snippet of RISCV 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 above macro to - * ignore it, otherwise LLVM eagerly emits compressed instructions for + * 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"; \ - runCompressed(sourceWithTerminator.c_str()); \ - } \ +#define RUN_RISCV_COMP(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), "+m,+a,+f,+d,+c"); \ + } \ if (HasFatalFailure()) return /** The test fixture for all RISCV regression tests. */ @@ -86,11 +86,7 @@ class RISCVRegressionTest : public RegressionTest { virtual ~RISCVRegressionTest() {} /** Run the assembly code in `source`. */ - void run(const char* source); - - /** Run the assembly code in `source` with compressed extension in the target - * ISA. */ - void runCompressed(const char* source); + void run(const char* source, const char* extensions); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; From a09cf77fba055aba9aee63fc89ef52706aba08ff Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 18:37:31 +0000 Subject: [PATCH 098/115] Update test and architecture --- src/include/simeng/arch/riscv/ArchInfo.hh | 2 -- src/include/simeng/arch/riscv/Architecture.hh | 3 --- src/lib/arch/riscv/Architecture.cc | 11 +++++++---- test/regression/riscv/CMakeLists.txt | 2 -- .../riscv/instructions/compressed.cc | 19 +++++-------------- 5 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index 75e5fcd678..effd728305 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -25,8 +25,6 @@ const uint8_t alignMask = 0x3; const uint8_t alignMaskCompressed = 0x1; const uint8_t bytesLimit = 4; const uint8_t bytesLimitCompressed = 2; -const uint8_t byteLength64 = 8; -const uint8_t byteLength32 = 4; }; // namespace constantsPool /** A class to hold and generate riscv specific architecture configuration diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index d8a8f5046f..599e186330 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -90,9 +90,6 @@ class Architecture : public arch::Architecture { /** A mask used to determine if an address has the correct byte alignment */ uint8_t alignMask; - /** Register width in bytes */ - uint8_t regWidth = constantsPool::byteLength64; - /** Minimum number of bytes that can represent an instruction */ uint8_t minInsnLength; }; diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index ec4fa5c4fb..a8175d466e 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -22,8 +22,8 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) cs_err n; - regWidth = constantsPool::byteLength64; - + // Check whether compressed instructions in use. Initialise variables and + // Capstone accordingly if (config["Core"]["Compressed"].as()) { alignMask = constantsPool::alignMaskCompressed; minInsnLength = constantsPool::bytesLimitCompressed; @@ -215,7 +215,9 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, auto iter = decodeCache.find(insn); if (iter == decodeCache.end()) { // No decoding present. Generate a fresh decoding, and add to cache - // Ensure cs_insn doesn't contain garbage data + // Calloc memory to ensure rawInsn is initialised with zeros. Errors can + // occur otherwise as Capstone doesn't update variables for invalid + // instructions cs_insn* rawInsnPointer = (cs_insn*)calloc(1, sizeof(cs_insn)); cs_insn rawInsn = *rawInsnPointer; assert(rawInsn.size == 0 && "rawInsn not initialised correctly"); @@ -232,7 +234,8 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, bool success = cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); - // size now contains size of next instruction in the buffer + // After cs_diasm_iter is called, size and address updated to contain the + // size/address of next instruction in the buffer auto metadata = success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding, rawInsn.size); diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index 1636b78369..4b39e35575 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -18,8 +18,6 @@ add_executable(regression-riscv target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(regression-riscv regression-test-base) -target_link_libraries(regression-riscv gmock_main) - # Define a macro so that tests can find data files target_compile_definitions(regression-riscv PRIVATE diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 16801adba4..6ec7c003c2 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -1,7 +1,4 @@ #include "RISCVRegressionTest.hh" -#include "gmock/gmock.h" - -using ::testing::HasSubstr; namespace { @@ -705,22 +702,16 @@ TEST_P(InstCompressed, nop) { TEST_P(InstCompressed, ebreak) { // Currently not implemented so ensure this produces an exception - std::stringstream buffer; - std::streambuf* sbuf = std::cout.rdbuf(); // Save cout's buffer - std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to buffer RUN_RISCV_COMP(R"( c.ebreak )"); - std::cout.rdbuf(sbuf); // Restore cout - EXPECT_THAT(buffer.str(), - HasSubstr("[SimEng:ExceptionHandler] Encountered execution " - "not-yet-implemented exception")); - EXPECT_THAT(buffer.str(), - HasSubstr("[SimEng:ExceptionHandler] 0x0000000000000000: 02 " - "90 c.ebreak")); - buffer.str(std::string()); + const char err1[] = + "\n[SimEng:ExceptionHandler] Encountered execution not-yet-implemented " + "exception\n[SimEng:ExceptionHandler] Generated by instruction: " + "\n[SimEng:ExceptionHandler] 0x0000000000000000: 02 90 c.ebreak"; + EXPECT_EQ(stdout_.substr(0, sizeof(err1) - 1), err1); } INSTANTIATE_TEST_SUITE_P(RISCV, InstCompressed, From 0bf5212ce98a6937fd03665b6267b4c1381f864c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 18:46:27 +0000 Subject: [PATCH 099/115] Update fetch unit --- src/lib/pipeline/FetchUnit.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 466da11332..524e18e9fa 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -85,14 +85,10 @@ void FetchUnit::tick() { } if (fetchIndex == fetched.size() && bufferedBytes_ < isa_.getMinInstructionSize()) { - // Need to wait for fetched instructions + // Relevant data has not been fetched and not enough data already in the + // buffer. Need to wait for fetched instructions return; - } else if (fetchIndex == fetched.size()) { - // There is minimal data already in the buffer which may be predecodable - // and no new data has been supplied - - // Do nothing and allow continuation - } else { + } else if (fetchIndex != fetched.size()) { // Data has been successfully read, move into fetch buffer // TODO: Handle memory faults assert(fetched[fetchIndex].data && "Memory read failed"); @@ -107,6 +103,11 @@ void FetchUnit::tick() { buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. bufferOffset = 0; + } else { + // Relevant data has not been fetched but there is minimal data already in + // the buffer. Attempt to predecode + + // Do nothing and allow continuation } } else { // There is already enough data in the fetch buffer, so use that From 995807398e1fc40d5892354e43512db42732dc89 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 18:55:48 +0000 Subject: [PATCH 100/115] Remove compressed wording from unit tests --- test/unit/pipeline/FetchUnitTest.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 3769d90c88..8d74481a8b 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -453,14 +453,14 @@ TEST_F(PipelineFetchUnitTest, idleLoopBufferDueToNotTakenBoundary) { EXPECT_EQ(output.getTailSlots()[0], mOp2); } -// Tests that a compressed instruction held at the end of the fetch buffer is +// Tests that a min sized instruction held at the end of the fetch buffer is // allowed to be predecoded in the same cycle as being fetched -TEST_F(PipelineFetchUnitTest, compressedInstructionAtEndOfBuffer) { +TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - // Buffer will contain valid compressed instruction so predecode returns + // Buffer will contain valid min size instruction so predecode returns // 2 bytes read MacroOp mOp = {uopPtr}; ON_CALL(isa, predecode(_, 2, 0xE, _)) @@ -560,7 +560,7 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { // Ensure progression with valid 2 bytes at end of buffer when next read doesn't // complete -TEST_F(PipelineFetchUnitTest, validCompressed_ReadsDontComplete) { +TEST_F(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); From 8f47ba7459ef9746b101ae82991cb98ff59ffa47 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 22:03:24 +0000 Subject: [PATCH 101/115] Updates regarding PR comments --- src/include/simeng/arch/riscv/ArchInfo.hh | 8 +-- src/include/simeng/arch/riscv/Architecture.hh | 4 +- src/include/simeng/pipeline/FetchUnit.hh | 4 +- src/lib/arch/riscv/Architecture.cc | 40 ++++++------ src/lib/arch/riscv/ExceptionHandler.cc | 6 +- src/lib/arch/riscv/InstructionMetadata.cc | 61 ++++++------------- src/lib/arch/riscv/Instruction_decode.cc | 9 ++- test/unit/pipeline/FetchUnitTest.cc | 2 +- 8 files changed, 55 insertions(+), 79 deletions(-) diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index effd728305..039d8e6ac5 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -21,10 +21,10 @@ typedef enum riscv_sysreg { // A struct of RISC-V specific constants namespace constantsPool { -const uint8_t alignMask = 0x3; -const uint8_t alignMaskCompressed = 0x1; -const uint8_t bytesLimit = 4; -const uint8_t bytesLimitCompressed = 2; +const uint8_t addressAlignMask = 0x3; +const uint8_t addressAlignMaskCompressed = 0x1; +const uint8_t minInstWidthBytes = 4; +const uint8_t minInstWidthBytesCompressed = 2; }; // namespace constantsPool /** A class to hold and generate riscv specific architecture configuration diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 599e186330..924d00ac96 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -88,10 +88,10 @@ class Architecture : public arch::Architecture { simeng::Register cycleSystemReg_; /** A mask used to determine if an address has the correct byte alignment */ - uint8_t alignMask; + uint8_t addressAlignmentMask_; /** Minimum number of bytes that can represent an instruction */ - uint8_t minInsnLength; + uint8_t minInsnLength_; }; } // namespace riscv diff --git a/src/include/simeng/pipeline/FetchUnit.hh b/src/include/simeng/pipeline/FetchUnit.hh index 0fd18ab926..080ee693d2 100644 --- a/src/include/simeng/pipeline/FetchUnit.hh +++ b/src/include/simeng/pipeline/FetchUnit.hh @@ -120,8 +120,8 @@ class FetchUnit { /** Let the following PipelineFetchUnitTest derived classes be a friend of * this class to allow proper testing of 'tick' function. */ friend class PipelineFetchUnitTest_invalidHalfWordAtEndOfBuffer_Test; - friend class PipelineFetchUnitTest_compressedInstructionAtEndOfBuffer_Test; - friend class PipelineFetchUnitTest_validCompressed_ReadsDontComplete_Test; + friend class PipelineFetchUnitTest_minSizeInstructionAtEndOfBuffer_Test; + friend class PipelineFetchUnitTest_validMinSize_ReadsDontComplete_Test; friend class PipelineFetchUnitTest_invalidHalfWord_readsDontComplete_Test; }; diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index a8175d466e..ea9addc619 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -25,15 +25,15 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) // Check whether compressed instructions in use. Initialise variables and // Capstone accordingly if (config["Core"]["Compressed"].as()) { - alignMask = constantsPool::alignMaskCompressed; - minInsnLength = constantsPool::bytesLimitCompressed; + addressAlignmentMask_ = constantsPool::addressAlignMaskCompressed; + minInsnLength_ = constantsPool::minInstWidthBytesCompressed; n = cs_open(CS_ARCH_RISCV, static_cast(CS_MODE_RISCV64 | CS_MODE_RISCVC), &capstoneHandle); } else { - alignMask = constantsPool::alignMask; - minInsnLength = constantsPool::bytesLimit; + addressAlignmentMask_ = constantsPool::addressAlignMask; + minInsnLength_ = constantsPool::minInstWidthBytes; n = cs_open(CS_ARCH_RISCV, static_cast(CS_MODE_RISCV64), &capstoneHandle); @@ -167,7 +167,7 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by RISC-V // 2-byte when Compressed extension is supported - if (instructionAddress & alignMask) { + if (instructionAddress & addressAlignmentMask_) { // Consume 1-byte and raise a misaligned PC exception auto metadata = InstructionMetadata((uint8_t*)ptr, 1); metadataCache.emplace_front(metadata); @@ -180,14 +180,14 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, return 1; } - assert(bytesAvailable >= minInsnLength && + assert(bytesAvailable >= minInsnLength_ && "Fewer than bytes limit supplied to RISC-V decoder"); // Get the first byte - uint8_t firstByte = *(uint8_t*)ptr; + uint8_t firstByte = ((uint8_t*)ptr)[0]; - uint32_t insn = 0; - size_t size = 4; + uint32_t insnEncoding = 0; + size_t insnSize = 4; // Predecode bytes to determine whether we have a compressed instruction. // This will allow continuation if a compressed instruction is in the last 2 @@ -199,8 +199,8 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, // 2 byte - compressed // Only use relevant bytes // Dereference the instruction pointer to obtain the instruction word - memcpy(&insn, ptr, 2); - size = 2; + memcpy(&insnEncoding, ptr, 2); + insnSize = 2; } else { // 4 byte if (bytesAvailable < 4) { @@ -208,11 +208,11 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, return 0; } // Dereference the instruction pointer to obtain the instruction word - memcpy(&insn, ptr, 4); + memcpy(&insnEncoding, ptr, 4); } // Try to find the decoding in the decode cache - auto iter = decodeCache.find(insn); + auto iter = decodeCache.find(insnEncoding); if (iter == decodeCache.end()) { // No decoding present. Generate a fresh decoding, and add to cache // Calloc memory to ensure rawInsn is initialised with zeros. Errors can @@ -226,14 +226,14 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, rawInsn.detail = &rawDetail; // Size requires initialisation in case of capstone failure which won't // update this value - rawInsn.size = size; + rawInsn.size = insnSize; uint64_t address = 0; const uint8_t* encoding = reinterpret_cast(ptr); - bool success = - cs_disasm_iter(capstoneHandle, &encoding, &size, &address, &rawInsn); + bool success = cs_disasm_iter(capstoneHandle, &encoding, &insnSize, + &address, &rawInsn); // After cs_diasm_iter is called, size and address updated to contain the // size/address of next instruction in the buffer @@ -251,13 +251,13 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, newInsn.setExecutionInfo(getExecutionInfo(newInsn)); // Cache the instruction - iter = decodeCache.insert({insn, newInsn}).first; + iter = decodeCache.insert({insnEncoding, newInsn}).first; } - assert(((insn & 0b11) != 0b11 + assert(((insnEncoding & 0b11) != 0b11 ? iter->second.getMetadata().getInsnLength() == 2 : iter->second.getMetadata().getInsnLength() == 4) && - "[SimEng:predecode] Predicted bytes don't match disassembled bytes"); + "Predicted number of bytes don't match disassembled number of bytes"); output.resize(1); auto& uop = output[0]; @@ -315,7 +315,7 @@ ProcessStateChange Architecture::getInitialState() const { uint8_t Architecture::getMaxInstructionSize() const { return 4; } -uint8_t Architecture::getMinInstructionSize() const { return minInsnLength; } +uint8_t Architecture::getMinInstructionSize() const { return minInsnLength_; } void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const { diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index c343f9f685..904707124d 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -914,12 +914,10 @@ void ExceptionHandler::printException(const Instruction& insn) const { << insn.getInstructionAddress() << ": "; auto& metadata = insn.getMetadata(); - for (uint8_t byteIndex = 0; byteIndex < insn.getMetadata().getInsnLength(); + for (uint8_t byteIndex = 0; byteIndex < metadata.getInsnLength(); byteIndex++) { std::cout << std::setfill('0') << std::setw(2) - << static_cast( - insn.getMetadata().encoding[byteIndex]) - << " "; + << static_cast(metadata.encoding[byteIndex]) << " "; } std::cout << std::dec << " "; if (exception == InstructionException::EncodingUnallocated) { diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 5c4ad3af74..6c4dd9c06f 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -486,8 +486,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rs1=zero is reserved assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && - "[SimEng:convertCompressedInstruction] C.JR has rs1=x0 which is " - "reserved"); + "C.JR has rs1=x0 which is reserved"); opcode = Opcode::RISCV_JALR; @@ -510,8 +509,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rs2 = zero corresponds to C.JR assert((operands[1].type == RISCV_OP_REG && operands[1].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.MV has rs2=x0 which is " - "invalid"); + "C.MV has rs2=x0 which is invalid"); opcode = Opcode::RISCV_ADD; @@ -526,8 +524,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rd = zero is reserved assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.LDSP has rd=x0 which is " - "reserved"); + "C.LDSP has rd=x0 which is reserved"); opcode = Opcode::RISCV_LD; @@ -541,8 +538,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // nzuimm = zero is reserved assert((operands[2].type == RISCV_OP_IMM && operands[2].imm != 0) && - "[SimEng:convertCompressedInstruction] C.ADDI4SPN has nzuimm=0 " - "which is reserved"); + "C.ADDI4SPN has nzuimm=0 which is reserved"); opcode = Opcode::RISCV_ADDI; // All operands correct @@ -554,8 +550,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rd = zero encodes hints assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.LI has rd=x0 which is " - "invalid"); + "C.LI has rd=x0 which is invalid"); opcode = Opcode::RISCV_ADDI; @@ -569,8 +564,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // nzimm = zero is reserved assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.ADDI16SP has nzimm=0 " - "which is reserved"); + "C.ADDI16SP has nzimm=0 which is reserved"); opcode = Opcode::RISCV_ADDI; @@ -590,14 +584,12 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // shamt = zero is reserved for hints assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.SLLI has shamt=0 " - "which is reserved for hints"); + "C.SLLI has shamt=0 which is reserved for hints"); // rd = zero encodes hints assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.SLLI has rd=x0 which is " - "reserved for hints"); + "C.SLLI has rd=x0 which is reserved for hints"); opcode = Opcode::RISCV_SLLI; @@ -636,17 +628,14 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rs2 = zero corresponds to C.JALR and C.EBREAK assert((operands[1].type == RISCV_OP_REG && operands[1].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 which is " - "invalid"); + "C.ADD has rs2=x0 which is invalid"); // rs2 = zero AND rd = zero are reserved for hints assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO && operands[1].type == RISCV_OP_REG && operands[1].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.ADD has rs2=x0 and rd=x0 " - "which is " - "reserved for hints"); + "C.ADD has rs2=x0 and rd=x0 which is reserved for hints"); opcode = Opcode::RISCV_ADD; @@ -671,13 +660,11 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rd = zero encodes C.NOP assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.ADDI has rd=x0 which is " - "invalid"); + "C.ADDI has rd=x0 which is invalid"); // nzimm = zero is reserved for hints assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.ADDI has nzimm=0 " - "which is reserved for hints"); + "C.ADDI has nzimm=0 which is reserved for hints"); opcode = Opcode::RISCV_ADDI; @@ -724,19 +711,16 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // nzimm = zero is reserved assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.LUI has nzimm=0 " - "which is reserved"); + "C.LUI has nzimm=0 which is reserved"); // rd = zero is reserved for hints assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.LUI has rd=x0 which is " - "reserved for hints"); + "C.LUI has rd=x0 which is reserved for hints"); // rd = x2 encodes C.ADDI16SP assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 3) && - "[SimEng:convertCompressedInstruction] C.LUI has rd=x2 which is " - "invalid"); + "C.LUI has rd=x2 which is invalid"); opcode = Opcode::RISCV_LUI; // all operands correct @@ -747,8 +731,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rd = zero is reserved assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.LWSP has rd=x0 which is " - "reserved"); + "C.LWSP has rd=x0 which is reserved"); opcode = Opcode::RISCV_LW; @@ -796,8 +779,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rd = zero is reserved assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.ADDIW has rd=x0 which is " - "reserved"); + "C.ADDIW has rd=x0 which is reserved"); opcode = Opcode::RISCV_ADDIW; @@ -826,8 +808,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // shamt = zero is reserved for hints assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.SRLI has shamt=0 " - "which is reserved for hints"); + "C.SRLI has shamt=0 which is reserved for hints"); opcode = Opcode::RISCV_SRLI; @@ -867,8 +848,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // rs1=zero corresponds to C.EBREAK instruction assert((operands[0].type == RISCV_OP_REG && operands[0].reg != RISCV_REG_ZERO) && - "[SimEng:convertCompressedInstruction] C.JALR has rs1=x0 which is " - "invalid"); + "C.JALR has rs1=x0 which is invalid"); opcode = Opcode::RISCV_JALR; @@ -897,8 +877,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // shamt = zero is reserved for hints assert((operands[1].type == RISCV_OP_IMM && operands[1].imm != 0) && - "[SimEng:convertCompressedInstruction] C.SRAI has shamt=0 " - "which is reserved for hints"); + "C.SRAI has shamt=0 which is reserved for hints"); opcode = Opcode::RISCV_SRAI; diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index 149cd52548..ac5725f698 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -210,15 +210,14 @@ void Instruction::decode() { sourceImm_ = op.imm; } else { // Something has gone wrong - assert( - false && - "[SimEng:Instruction_decode] Unexpected register type in non-first " - "operand position"); + assert(false && + "Unexpected register type in non-first " + "operand position"); } } else { // Something has gone wrong assert(false && - "[SimEng:Instruction_decode] Unexpected register type in first " + "Unexpected register type in first " "operand position"); } } diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 8d74481a8b..cb806a9667 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -676,7 +676,7 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { // Tick fetchUnit.tick(); - // Ensure 2 bytes are consumed + // Ensure 2 bytes are not consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 2); EXPECT_EQ(fetchUnit.pc_, 14); } From 2876560cfb108ac7ecc28febb7344c1800531415 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 22:35:03 +0000 Subject: [PATCH 102/115] Update docs and unit tests --- docs/sphinx/user/configuring_simeng.rst | 3 +++ test/unit/pipeline/FetchUnitTest.cc | 31 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/sphinx/user/configuring_simeng.rst b/docs/sphinx/user/configuring_simeng.rst index 344585f77b..62520290db 100644 --- a/docs/sphinx/user/configuring_simeng.rst +++ b/docs/sphinx/user/configuring_simeng.rst @@ -52,6 +52,9 @@ Vector-Length (Only in use when ISA is ``AArch64``) Streaming-Vector-Length (Only in use when ISA is ``AArch64``) The vector length used by instructions belonging to Arm's Scalable Matrix Extension. Although the architecturally valid vector lengths are powers of 2 between 128 and 2048 inclusive, the supported vector lengths are those between 128 and 2048 in increments of 128. +Compressed (Only in use when ISA is ``rv64``) + Enables the RISC-V compressed extension. If set to false and compressed instructions are supplied, a misaligned program counter exception is usually thrown. + Fetch ----- diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index cb806a9667..d412e14f97 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -480,6 +480,7 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { // Buffer should now be empty as all bytes predecoded EXPECT_EQ(fetchUnit.bufferedBytes_, 0); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); // Expect a block starting at address 16 to be requested when we fetch again EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); @@ -488,11 +489,12 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { fetchUnit.requestFromPC(); // Tick again, expecting that decoding will now resume + MacroOp mOp2 = {uopPtr2}; MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; span nextBlock = {&nextBlockValue, 1}; ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); ON_CALL(isa, predecode(_, _, _, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); + .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(4))); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); // Completed reads called again as more data is requested @@ -505,6 +507,7 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { // Initially 0 bytes, 16 bytes added, 4 bytes predecoded leaving 12 bytes left EXPECT_EQ(fetchUnit.bufferedBytes_, 12); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); } // Test that invalid half byte held at the end of the buffer is not successfully @@ -515,9 +518,8 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read - MacroOp mOp = {uopPtr}; - ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + // TODO is this correct way to not change output + ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInstructionSize called for second time in assertion EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); @@ -532,6 +534,8 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { // No data consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 2); + // TODO ensure this is correct + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); // Expect that memory is requested even though there is data in the buffer as // bufferedBytes < maxInstructionSize @@ -541,6 +545,7 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { fetchUnit.requestFromPC(); // Tick again expecting buffer to be filled and a word is predecoded + MacroOp mOp = {uopPtr}; MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; span nextBlock = {&nextBlockValue, 1}; ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); @@ -556,6 +561,7 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { // Initially 2 bytes, 16 bytes added, 4 bytes predecoded leaving 14 bytes left EXPECT_EQ(fetchUnit.bufferedBytes_, 14); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); } // Ensure progression with valid 2 bytes at end of buffer when next read doesn't @@ -586,6 +592,7 @@ TEST_F(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { // Ensure 4 bytes consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 2); EXPECT_EQ(fetchUnit.pc_, 14); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); // Expect that memory is requested even though there is data in the buffer as // bufferedBytes < maxInstructionSize @@ -599,10 +606,11 @@ TEST_F(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { // Memory doesn't complete reads in next cycle but buffered bytes should be // predecoded + MacroOp mOp2 = {uopPtr2}; ON_CALL(memory, getCompletedReads()) .WillByDefault(Return(span{nullptr, 0})); ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(2))); + .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(2))); // Path through fetch as follows: // More data required as bufferedBytes_ < maxInsnSize so getCompletedReads @@ -620,6 +628,7 @@ TEST_F(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { // Ensure 2 bytes are consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 0); EXPECT_EQ(fetchUnit.pc_, 16); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); } // Test that invalid half byte held at the end of the buffer is not successfully @@ -630,9 +639,8 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read - MacroOp mOp = {uopPtr}; - ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + // TODO is this correct way to not change output + ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInstructionSize called for second time in assertion EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); @@ -648,6 +656,8 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { // No data consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 2); EXPECT_EQ(fetchUnit.pc_, 14); + // TODO ensure this is correct + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); // Expect that memory is requested even though there is data in the buffer as // bufferedBytes < maxInstructionSize @@ -664,8 +674,7 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { ON_CALL(memory, getCompletedReads()) .WillByDefault(Return(span{nullptr, 0})); // Predecode still returns no bytes read - ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(0))); + ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInsnSize called again in assertion EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); @@ -679,6 +688,8 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { // Ensure 2 bytes are not consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 2); EXPECT_EQ(fetchUnit.pc_, 14); + // TODO ensure this is correct + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); } } // namespace pipeline From a9e3bec3b9199c549898a761b35be35f8612cf34 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sun, 18 Feb 2024 19:05:59 +0000 Subject: [PATCH 103/115] Add build type conditions to fetch units tests --- test/unit/pipeline/FetchUnitTest.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index d412e14f97..5a2b5adc2e 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -522,7 +522,11 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInstructionSize called for second time in assertion - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); @@ -643,7 +647,11 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInstructionSize called for second time in assertion - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); @@ -677,7 +685,11 @@ TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); // getMaxInsnSize called again in assertion - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } EXPECT_CALL(memory, getCompletedReads()).Times(1); EXPECT_CALL(isa, getMinInstructionSize()).Times(2); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); From 45f8afcc008c6a62347a869211674791626f88cd Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 15:14:34 +0000 Subject: [PATCH 104/115] Parameterise tests --- test/unit/pipeline/FetchUnitTest.cc | 423 +++++++++++++++------------- 1 file changed, 227 insertions(+), 196 deletions(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 2a22a2277c..81c8021ed7 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -25,7 +25,8 @@ using ::testing::SetArgReferee; namespace simeng { namespace pipeline { -class PipelineFetchUnitTest : public testing::Test { +class PipelineFetchUnitTest + : public testing::TestWithParam> { public: PipelineFetchUnitTest() : output(1, {}), @@ -43,8 +44,8 @@ class PipelineFetchUnitTest : public testing::Test { } protected: - const uint8_t insnMaxSizeBytes = 4; - const uint8_t insnMinSizeBytes = 2; + const uint8_t insnMinSizeBytes = GetParam().first; + const uint8_t insnMaxSizeBytes = GetParam().second; const uint8_t blockSize = 16; PipelineBuffer output; @@ -66,7 +67,7 @@ class PipelineFetchUnitTest : public testing::Test { // Tests that ticking a fetch unit attempts to predecode from the correct // program counter and generates output correctly. -TEST_F(PipelineFetchUnitTest, Tick) { +TEST_P(PipelineFetchUnitTest, Tick) { MacroOp macroOp = {uopPtr}; ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); @@ -84,7 +85,7 @@ TEST_F(PipelineFetchUnitTest, Tick) { } // Tests that ticking a fetch unit does nothing if the output has stalled -TEST_F(PipelineFetchUnitTest, TickStalled) { +TEST_P(PipelineFetchUnitTest, TickStalled) { output.stall(true); // Anticipate testing instruction type; return true for branch @@ -102,15 +103,17 @@ TEST_F(PipelineFetchUnitTest, TickStalled) { // Tests that the fetch unit will handle instructions that straddle fetch block // boundaries by automatically requesting the next block of data. -TEST_F(PipelineFetchUnitTest, FetchUnaligned) { +TEST_P(PipelineFetchUnitTest, FetchUnaligned) { MacroOp mOp = {uopPtr}; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - // Set PC to 15, so there will not be enough data to start decoding + assert(insnMinSizeBytes > 1 && "min insn size too small to set PC correctly"); + uint64_t setPC = (blockSize - insnMinSizeBytes) + 1; + // Set PC so that there will not be enough data to start decoding EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0); - fetchUnit.updatePC(15); + fetchUnit.updatePC(setPC); fetchUnit.tick(); // Expect a block starting at address 16 to be requested when we fetch again @@ -145,7 +148,7 @@ TEST_F(PipelineFetchUnitTest, FetchUnaligned) { // Tests that a properly aligned PC (to the fetch block boundary) is correctly // fetched -TEST_F(PipelineFetchUnitTest, fetchAligned) { +TEST_P(PipelineFetchUnitTest, fetchAligned) { const uint8_t pc = 16; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); @@ -186,7 +189,7 @@ TEST_F(PipelineFetchUnitTest, fetchAligned) { } // Tests that halting functionality triggers correctly -TEST_F(PipelineFetchUnitTest, halted) { +TEST_P(PipelineFetchUnitTest, halted) { ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); EXPECT_FALSE(fetchUnit.hasHalted()); @@ -228,7 +231,7 @@ TEST_F(PipelineFetchUnitTest, halted) { // Tests that fetching a branch instruction (predicted taken) mid block causes a // branch stall + discards the remaining fetched instructions -TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { +TEST_P(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { const uint8_t pc = 16; ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); @@ -294,7 +297,7 @@ TEST_F(PipelineFetchUnitTest, fetchTakenBranchMidBlock) { } // Tests the functionality of the supplying from the Loop Buffer -TEST_F(PipelineFetchUnitTest, supplyFromLoopBuffer) { +TEST_P(PipelineFetchUnitTest, supplyFromLoopBuffer) { // Set instructions to be fetched from memory memory::MemoryReadResult memReadResult = { {0x0, blockSize}, RegisterValue(0xFFFF, blockSize), 1}; @@ -383,7 +386,7 @@ TEST_F(PipelineFetchUnitTest, supplyFromLoopBuffer) { // Tests the functionality of idling the supply to the Loop Buffer one of not // taken branch at the loopBoundaryAddress_ -TEST_F(PipelineFetchUnitTest, idleLoopBufferDueToNotTakenBoundary) { +TEST_P(PipelineFetchUnitTest, idleLoopBufferDueToNotTakenBoundary) { // Set instructions to be fetched from memory memory::MemoryReadResult memReadResultA = { {0x0, blockSize}, RegisterValue(0xFFFF, blockSize), 1}; @@ -460,7 +463,7 @@ TEST_F(PipelineFetchUnitTest, idleLoopBufferDueToNotTakenBoundary) { // Tests that a min sized instruction held at the end of the fetch buffer is // allowed to be predecoded in the same cycle as being fetched -TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { +TEST_P(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); @@ -468,8 +471,8 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { // Buffer will contain valid min size instruction so predecode returns // 2 bytes read MacroOp mOp = {uopPtr}; - ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(2))); + ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(insnMinSizeBytes))); // Fetch the data, only 2 bytes will be copied to fetch buffer. Should allow // continuation to predecode @@ -478,8 +481,9 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { EXPECT_CALL(isa, getMinInstructionSize()).Times(1); EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - // Set PC to 14, buffered bytes = 0 - fetchUnit.updatePC(14); + uint64_t setPC = blockSize - insnMinSizeBytes; + // Fetch a single minimum sized instruction, buffered bytes = 0 + fetchUnit.updatePC(setPC); // Tick. Fetch data and predecode fetchUnit.tick(); @@ -500,7 +504,7 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { span nextBlock = {&nextBlockValue, 1}; ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); ON_CALL(isa, predecode(_, _, _, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(4))); + .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(insnMaxSizeBytes))); EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); // Completed reads called again as more data is requested @@ -511,207 +515,234 @@ TEST_F(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { fetchUnit.tick(); - // Initially 0 bytes, 16 bytes added, 4 bytes predecoded leaving 12 bytes left - EXPECT_EQ(fetchUnit.bufferedBytes_, 12); + // Initially 0 bytes, 16 bytes added, max bytes predecoded leaving 16-max + // bytes left + EXPECT_EQ(fetchUnit.bufferedBytes_, 16 - insnMaxSizeBytes); EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); } -// Test that invalid half byte held at the end of the buffer is not successfully -// predecoded and that more data is fetched subsequently allowing progression -TEST_F(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { - ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); - ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); - ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); +// Test that invalid min number of bytes held at the end of the buffer is not +// successfully predecoded and that more data is fetched subsequently allowing +// progression as a full instruction is now present in the buffer +TEST_P(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { + // This is only relevant if min and max size are different. Otherwise, there + // won't be any progression as the fetch unit will be caught in an infinite + // loop + if (insnMinSizeBytes < insnMaxSizeBytes) { + ON_CALL(isa, getMaxInstructionSize()) + .WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()) + .WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) + .WillByDefault(Return(0)); + + // getMaxInstructionSize called for second time in assertion + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + uint64_t setPC = blockSize - insnMinSizeBytes; + // Fetch a single minimum sized instruction, buffered bytes = 0 + fetchUnit.updatePC(setPC); + // Tick + fetchUnit.tick(); - // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read - // TODO is this correct way to not change output - ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); + // No data consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); - // getMaxInstructionSize called for second time in assertion - if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + // Expect that memory is requested even though there is data in the buffer + // as bufferedBytes < maxInstructionSize EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - } else { - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); - } - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(1); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - - // Set PC to 14, buffered bytes = 0 - fetchUnit.updatePC(14); - // Tick - fetchUnit.tick(); - - // No data consumed - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - // TODO ensure this is correct - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); - - // Expect that memory is requested even though there is data in the buffer as - // bufferedBytes < maxInstructionSize - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, - requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) - .Times(1); - fetchUnit.requestFromPC(); - - // Tick again expecting buffer to be filled and a word is predecoded - MacroOp mOp = {uopPtr}; - memory::MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; - span nextBlock = {&nextBlockValue, 1}; - ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); - ON_CALL(isa, predecode(_, _, _, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); + EXPECT_CALL(memory, + requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + // Tick again expecting buffer to be filled and a word is predecoded + MacroOp mOp = {uopPtr}; + memory::MemoryReadResult nextBlockValue = {{16, blockSize}, 0, 1}; + span nextBlock = {&nextBlockValue, 1}; + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(nextBlock)); + ON_CALL(isa, predecode(_, _, _, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(insnMaxSizeBytes))); - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(1); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - fetchUnit.tick(); + fetchUnit.tick(); - // Initially 2 bytes, 16 bytes added, 4 bytes predecoded leaving 14 bytes left - EXPECT_EQ(fetchUnit.bufferedBytes_, 14); - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); + // Initially 2 bytes, 16 bytes added, 4 bytes predecoded leaving 14 bytes + // left + EXPECT_EQ(fetchUnit.bufferedBytes_, (2 + 16) - insnMaxSizeBytes); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); + } } -// Ensure progression with valid 2 bytes at end of buffer when next read doesn't -// complete -TEST_F(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { - ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); - ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); - ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - - // Buffer will contain valid 6 bytes so predecode returns 4 bytes read on - // first tick - MacroOp mOp = {uopPtr}; - ON_CALL(isa, predecode(_, 6, 0xA, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(4))); - - // Fetch the data, only last 6 bytes from block. Should allow continuation to - // predecode - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(1); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - - // Set PC to 10, buffered bytes = 0 - fetchUnit.updatePC(10); - // Tick and predecode 4 bytes - fetchUnit.tick(); - - // Ensure 4 bytes consumed - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - EXPECT_EQ(fetchUnit.pc_, 14); - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); - - // Expect that memory is requested even though there is data in the buffer as - // bufferedBytes < maxInstructionSize - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, - requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) - .Times(1); - fetchUnit.requestFromPC(); - - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - EXPECT_EQ(fetchUnit.pc_, 14); +// When min and max instruction sizes are different, ensure progression with +// valid min sized instruction at end of buffer when next read doesn't complete. +TEST_P(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { + // In the case that min and max are the same, memory is never requested as + // there is enough data in the buffer. In this case, the test isn't relevant + if (insnMinSizeBytes < insnMaxSizeBytes) { + ON_CALL(isa, getMaxInstructionSize()) + .WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()) + .WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain valid max and min sized instruction, predecode + // returns max bytes read on first tick + MacroOp mOp = {uopPtr}; + ON_CALL(isa, predecode(_, insnMaxSizeBytes + insnMinSizeBytes, + 0x10 - (insnMaxSizeBytes + insnMinSizeBytes), _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(insnMaxSizeBytes))); + + // Fetch the data, only last max + min bytes from block. Should allow + // continuation to predecode + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + uint64_t setPC = blockSize - (insnMaxSizeBytes + insnMinSizeBytes); + // Fetch a minimum and maximum sized instruction, buffered bytes = 0 + fetchUnit.updatePC(setPC); + // Tick and predecode 4 bytes + fetchUnit.tick(); - // Memory doesn't complete reads in next cycle but buffered bytes should be - // predecoded - MacroOp mOp2 = {uopPtr2}; - ON_CALL(memory, getCompletedReads()) - .WillByDefault(Return(span{nullptr, 0})); - ON_CALL(isa, predecode(_, 2, 0xE, _)) - .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(2))); + // Ensure max bytes consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); - // Path through fetch as follows: - // More data required as bufferedBytes_ < maxInsnSize so getCompletedReads - // Doesn't complete so buffer doesn't get added to - // Buffer still has some valid data so predecode should be called + // Expect that memory is requested even though there is data in the buffer + // as bufferedBytes < maxInstructionSize + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, + requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); + + // Memory doesn't complete reads in next cycle but buffered bytes should be + // predecoded + MacroOp mOp2 = {uopPtr2}; + ON_CALL(memory, getCompletedReads()) + .WillByDefault(Return(span{nullptr, 0})); + ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) + .WillByDefault(DoAll(SetArgReferee<3>(mOp2), Return(insnMinSizeBytes))); + + // Path through fetch as follows: + // More data required as bufferedBytes_ < maxInsnSize so getCompletedReads + // Doesn't complete so buffer doesn't get added to + // Buffer still has some valid data so predecode should be called - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(2); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(2); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - // Tick - fetchUnit.tick(); + // Tick + fetchUnit.tick(); - // Ensure 2 bytes are consumed - EXPECT_EQ(fetchUnit.bufferedBytes_, 0); - EXPECT_EQ(fetchUnit.pc_, 16); - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); + // Ensure 2 bytes are consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, 0); + EXPECT_EQ(fetchUnit.pc_, 16); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); + } } -// Test that invalid half byte held at the end of the buffer is not successfully -// predecoded and should be retried when reads don't complete -TEST_F(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { - ON_CALL(isa, getMaxInstructionSize()).WillByDefault(Return(insnMaxSizeBytes)); - ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); - ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); +// Test that minimum bytes held at the end of the buffer is not successfully +// predecoded and should be re-tried when reads don't complete +TEST_P(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { + // In the case where min and max are the same, predecode will never return 0 + // so the test is only relevent in the case where they are different + if (insnMinSizeBytes < insnMaxSizeBytes) { + ON_CALL(isa, getMaxInstructionSize()) + .WillByDefault(Return(insnMaxSizeBytes)); + ON_CALL(isa, getMinInstructionSize()) + .WillByDefault(Return(insnMinSizeBytes)); + ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); + + // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) + .WillByDefault(Return(0)); + + // getMaxInstructionSize called for second time in assertion + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(1); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + uint64_t setPC = blockSize - insnMinSizeBytes; + // Fetch a minimum number of bytes, buffered bytes = 0 + fetchUnit.updatePC(setPC); + // Tick + fetchUnit.tick(); - // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read - // TODO is this correct way to not change output - ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); + // No data consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); - // getMaxInstructionSize called for second time in assertion - if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + // Expect that memory is requested even though there is data in the buffer + // as bufferedBytes < maxInstructionSize EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - } else { - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); - } - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(1); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - - // Set PC to 14, buffered bytes = 0 - fetchUnit.updatePC(14); - // Tick - fetchUnit.tick(); - - // No data consumed - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - EXPECT_EQ(fetchUnit.pc_, 14); - // TODO ensure this is correct - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); - - // Expect that memory is requested even though there is data in the buffer as - // bufferedBytes < maxInstructionSize - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - EXPECT_CALL(memory, - requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) - .Times(1); - fetchUnit.requestFromPC(); - - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - EXPECT_EQ(fetchUnit.pc_, 14); - - // Memory doesn't complete reads in next cycle but buffered bytes should - // attempt to be predecoded - ON_CALL(memory, getCompletedReads()) - .WillByDefault(Return(span{nullptr, 0})); - // Predecode still returns no bytes read - ON_CALL(isa, predecode(_, 2, 0xE, _)).WillByDefault(Return(0)); + EXPECT_CALL(memory, + requestRead(Field(&memory::MemoryAccessTarget::address, 16), _)) + .Times(1); + fetchUnit.requestFromPC(); + + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); + + // Memory doesn't complete reads in next cycle but buffered bytes should + // attempt to be predecoded + ON_CALL(memory, getCompletedReads()) + .WillByDefault(Return(span{nullptr, 0})); + // Predecode still returns no bytes read + ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) + .WillByDefault(Return(0)); + + // getMaxInsnSize called again in assertion + if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); + } else { + EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + } + EXPECT_CALL(memory, getCompletedReads()).Times(1); + EXPECT_CALL(isa, getMinInstructionSize()).Times(2); + EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); + + // Tick + fetchUnit.tick(); - // getMaxInsnSize called again in assertion - if (strcmp(SIMENG_BUILD_TYPE, "Release") == 0) { - EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); - } else { - EXPECT_CALL(isa, getMaxInstructionSize()).Times(2); + // Ensure 2 bytes are not consumed + EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); + EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); + EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); } - EXPECT_CALL(memory, getCompletedReads()).Times(1); - EXPECT_CALL(isa, getMinInstructionSize()).Times(2); - EXPECT_CALL(isa, predecode(_, _, _, _)).Times(1); - - // Tick - fetchUnit.tick(); - - // Ensure 2 bytes are not consumed - EXPECT_EQ(fetchUnit.bufferedBytes_, 2); - EXPECT_EQ(fetchUnit.pc_, 14); - // TODO ensure this is correct - EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); } +INSTANTIATE_TEST_SUITE_P(PipelineFetchUnitTests, PipelineFetchUnitTest, + ::testing::Values(std::pair(2, 4), std::pair(4, 4))); + } // namespace pipeline } // namespace simeng From 12ce7c6717b5a681c18c713cec0fe0776a37aa8f Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 15:21:53 +0000 Subject: [PATCH 105/115] Use cs register enum in all cases --- src/lib/arch/riscv/InstructionMetadata.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 6c4dd9c06f..0de57392bb 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -163,7 +163,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { operands[0].reg = RISCV_REG_ZERO; operands[1].type = RISCV_OP_REG; - operands[1].reg = 2; + operands[1].reg = RISCV_REG_RA; operands[2].type = RISCV_OP_IMM; operands[2].imm = 0; @@ -185,7 +185,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // jalr Rs is pseudo of JALR x1, Rs, 0 // JALR Rs, _, _ -> JALR x1, Rs, 0 operands[0].type = RISCV_OP_REG; - operands[0].reg = 2; + operands[0].reg = RISCV_REG_RA; operands[1] = insn.detail->riscv.operands[0]; @@ -201,7 +201,7 @@ void InstructionMetadata::alterPseudoInstructions(const cs_insn& insn) { // jal offset is pseudo of JAL x1, offset // JAL offset, _ -> JAL x1, offset operands[0].type = RISCV_OP_REG; - operands[0].reg = 2; + operands[0].reg = RISCV_REG_RA; operands[1].type = RISCV_OP_IMM; operands[1].imm = insn.detail->riscv.operands[0].imm; @@ -485,7 +485,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // C.JR rs1, _, _ -> JALR x0, rs1, 0 // rs1=zero is reserved - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 1) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_ZERO) && "C.JR has rs1=x0 which is reserved"); opcode = Opcode::RISCV_JALR; @@ -719,7 +720,8 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { "C.LUI has rd=x0 which is reserved for hints"); // rd = x2 encodes C.ADDI16SP - assert((operands[0].type == RISCV_OP_REG && operands[0].reg != 3) && + assert((operands[0].type == RISCV_OP_REG && + operands[0].reg != RISCV_REG_SP) && "C.LUI has rd=x2 which is invalid"); opcode = Opcode::RISCV_LUI; @@ -854,7 +856,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { operands[1] = operands[0]; - operands[0].reg = 2; + operands[0].reg = RISCV_REG_RA; operands[2].type = RISCV_OP_IMM; operands[2].imm = 0; From 6c6642beff9cd6e91ea833a808b14540c63dfa5b Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 16:34:24 +0000 Subject: [PATCH 106/115] Capitalise --- src/lib/arch/riscv/InstructionMetadata.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 0de57392bb..bb98656d4b 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -725,7 +725,7 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { "C.LUI has rd=x2 which is invalid"); opcode = Opcode::RISCV_LUI; - // all operands correct + // All operands correct break; case Opcode::RISCV_C_LWSP: { // lw rd, offset[7:2](x2) From 848c1ae794d11a0befd182a84238af5263aec94c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 21:19:02 +0000 Subject: [PATCH 107/115] PR comments --- src/include/simeng/pipeline/FetchUnit.hh | 4 ++-- src/lib/arch/riscv/Architecture.cc | 2 -- test/unit/pipeline/FetchUnitTest.cc | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/include/simeng/pipeline/FetchUnit.hh b/src/include/simeng/pipeline/FetchUnit.hh index b72058c64b..d9ec9e4df4 100644 --- a/src/include/simeng/pipeline/FetchUnit.hh +++ b/src/include/simeng/pipeline/FetchUnit.hh @@ -122,8 +122,8 @@ class FetchUnit { * this class to allow proper testing of 'tick' function. */ friend class PipelineFetchUnitTest_invalidHalfWordAtEndOfBuffer_Test; friend class PipelineFetchUnitTest_minSizeInstructionAtEndOfBuffer_Test; - friend class PipelineFetchUnitTest_validMinSize_ReadsDontComplete_Test; - friend class PipelineFetchUnitTest_invalidHalfWord_readsDontComplete_Test; + friend class PipelineFetchUnitTest_validMinSizeReadsDontComplete_Test; + friend class PipelineFetchUnitTest_invalidHalfWordreadsDontComplete_Test; }; } // namespace pipeline diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index df196e8f8a..3cb17ae2c8 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -227,8 +227,6 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, bool success = cs_disasm_iter(capstoneHandle_, &encoding, &insnSize, &address, &rawInsn); - // After cs_diasm_iter is called, size and address updated to contain the - // size/address of next instruction in the buffer auto metadata = success ? InstructionMetadata(rawInsn) : InstructionMetadata(encoding, rawInsn.size); diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 81c8021ed7..830bc12b69 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -591,7 +591,7 @@ TEST_P(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { // When min and max instruction sizes are different, ensure progression with // valid min sized instruction at end of buffer when next read doesn't complete. -TEST_P(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { +TEST_P(PipelineFetchUnitTest, validMinSizeReadsDontComplete) { // In the case that min and max are the same, memory is never requested as // there is enough data in the buffer. In this case, the test isn't relevant if (insnMinSizeBytes < insnMaxSizeBytes) { @@ -667,7 +667,7 @@ TEST_P(PipelineFetchUnitTest, validMinSize_ReadsDontComplete) { // Test that minimum bytes held at the end of the buffer is not successfully // predecoded and should be re-tried when reads don't complete -TEST_P(PipelineFetchUnitTest, invalidHalfWord_readsDontComplete) { +TEST_P(PipelineFetchUnitTest, invalidHalfWordreadsDontComplete) { // In the case where min and max are the same, predecode will never return 0 // so the test is only relevent in the case where they are different if (insnMinSizeBytes < insnMaxSizeBytes) { From b06672e4a2c9267ad1e2255667e306b0d1f0ca1c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 21:19:20 +0000 Subject: [PATCH 108/115] Update fetch unit comment --- src/lib/pipeline/FetchUnit.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 7fedbadc4b..a74bf66a05 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -83,6 +83,9 @@ void FetchUnit::tick() { break; } } + // Decide how to progress based on status of fetched data and buffer. Allow + // progression if minimal data is in the buffer no matter state of fetched + // data if (fetchIndex == fetched.size() && bufferedBytes_ < isa_.getMinInstructionSize()) { // Relevant data has not been fetched and not enough data already in the @@ -103,11 +106,6 @@ void FetchUnit::tick() { buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. bufferOffset = 0; - } else { - // Relevant data has not been fetched but there is minimal data already in - // the buffer. Attempt to predecode - - // Do nothing and allow continuation } } else { // There is already enough data in the fetch buffer, so use that From f22b0daa139a954a3052ad977b2937ef0f6fec56 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 16:09:57 +0000 Subject: [PATCH 109/115] Update fetch unit comments inline with new parameterisation --- src/include/simeng/pipeline/FetchUnit.hh | 4 ++-- test/unit/pipeline/FetchUnitTest.cc | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/include/simeng/pipeline/FetchUnit.hh b/src/include/simeng/pipeline/FetchUnit.hh index d9ec9e4df4..0c617a5547 100644 --- a/src/include/simeng/pipeline/FetchUnit.hh +++ b/src/include/simeng/pipeline/FetchUnit.hh @@ -120,10 +120,10 @@ class FetchUnit { /** Let the following PipelineFetchUnitTest derived classes be a friend of * this class to allow proper testing of 'tick' function. */ - friend class PipelineFetchUnitTest_invalidHalfWordAtEndOfBuffer_Test; + friend class PipelineFetchUnitTest_invalidMinBytesAtEndOfBuffer_Test; friend class PipelineFetchUnitTest_minSizeInstructionAtEndOfBuffer_Test; friend class PipelineFetchUnitTest_validMinSizeReadsDontComplete_Test; - friend class PipelineFetchUnitTest_invalidHalfWordreadsDontComplete_Test; + friend class PipelineFetchUnitTest_invalidMinBytesreadsDontComplete_Test; }; } // namespace pipeline diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index 830bc12b69..e640bdd343 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -469,12 +469,12 @@ TEST_P(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); // Buffer will contain valid min size instruction so predecode returns - // 2 bytes read + // min bytes read MacroOp mOp = {uopPtr}; ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) .WillByDefault(DoAll(SetArgReferee<3>(mOp), Return(insnMinSizeBytes))); - // Fetch the data, only 2 bytes will be copied to fetch buffer. Should allow + // Fetch the data, only min bytes will be copied to fetch buffer. Should allow // continuation to predecode EXPECT_CALL(isa, getMaxInstructionSize()).Times(1); EXPECT_CALL(memory, getCompletedReads()).Times(1); @@ -515,7 +515,7 @@ TEST_P(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { fetchUnit.tick(); - // Initially 0 bytes, 16 bytes added, max bytes predecoded leaving 16-max + // Initially 0 bytes, 16 bytes added, max bytes predecoded leaving (16 - max) // bytes left EXPECT_EQ(fetchUnit.bufferedBytes_, 16 - insnMaxSizeBytes); EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); @@ -524,7 +524,7 @@ TEST_P(PipelineFetchUnitTest, minSizeInstructionAtEndOfBuffer) { // Test that invalid min number of bytes held at the end of the buffer is not // successfully predecoded and that more data is fetched subsequently allowing // progression as a full instruction is now present in the buffer -TEST_P(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { +TEST_P(PipelineFetchUnitTest, invalidMinBytesAtEndOfBuffer) { // This is only relevant if min and max size are different. Otherwise, there // won't be any progression as the fetch unit will be caught in an infinite // loop @@ -582,9 +582,9 @@ TEST_P(PipelineFetchUnitTest, invalidHalfWordAtEndOfBuffer) { fetchUnit.tick(); - // Initially 2 bytes, 16 bytes added, 4 bytes predecoded leaving 14 bytes - // left - EXPECT_EQ(fetchUnit.bufferedBytes_, (2 + 16) - insnMaxSizeBytes); + // Initially min bytes, 16 bytes added, max bytes predecoded + EXPECT_EQ(fetchUnit.bufferedBytes_, + (insnMinSizeBytes + 16) - insnMaxSizeBytes); EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp); } } @@ -618,7 +618,7 @@ TEST_P(PipelineFetchUnitTest, validMinSizeReadsDontComplete) { uint64_t setPC = blockSize - (insnMaxSizeBytes + insnMinSizeBytes); // Fetch a minimum and maximum sized instruction, buffered bytes = 0 fetchUnit.updatePC(setPC); - // Tick and predecode 4 bytes + // Tick and predecode max bytes fetchUnit.tick(); // Ensure max bytes consumed @@ -658,7 +658,7 @@ TEST_P(PipelineFetchUnitTest, validMinSizeReadsDontComplete) { // Tick fetchUnit.tick(); - // Ensure 2 bytes are consumed + // Ensure min bytes are consumed EXPECT_EQ(fetchUnit.bufferedBytes_, 0); EXPECT_EQ(fetchUnit.pc_, 16); EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], mOp2); @@ -667,7 +667,7 @@ TEST_P(PipelineFetchUnitTest, validMinSizeReadsDontComplete) { // Test that minimum bytes held at the end of the buffer is not successfully // predecoded and should be re-tried when reads don't complete -TEST_P(PipelineFetchUnitTest, invalidHalfWordreadsDontComplete) { +TEST_P(PipelineFetchUnitTest, invalidMinBytesreadsDontComplete) { // In the case where min and max are the same, predecode will never return 0 // so the test is only relevent in the case where they are different if (insnMinSizeBytes < insnMaxSizeBytes) { @@ -677,7 +677,7 @@ TEST_P(PipelineFetchUnitTest, invalidHalfWordreadsDontComplete) { .WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + // Buffer will contain invalid min bytes so predecode returns 0 bytes read ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) .WillByDefault(Return(0)); @@ -734,7 +734,7 @@ TEST_P(PipelineFetchUnitTest, invalidHalfWordreadsDontComplete) { // Tick fetchUnit.tick(); - // Ensure 2 bytes are not consumed + // Ensure min bytes are not consumed EXPECT_EQ(fetchUnit.bufferedBytes_, insnMinSizeBytes); EXPECT_EQ(fetchUnit.pc_, blockSize - insnMinSizeBytes); EXPECT_EQ(fetchUnit.output_.getTailSlots()[0], MacroOp()); From b72ddda33e5f3fe418e5fb433baa185c238c4c2f Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 16:12:15 +0000 Subject: [PATCH 110/115] Move comment in instruction decode --- src/lib/arch/riscv/Instruction_decode.cc | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/lib/arch/riscv/Instruction_decode.cc b/src/lib/arch/riscv/Instruction_decode.cc index c48e20b188..95d1b426d9 100644 --- a/src/lib/arch/riscv/Instruction_decode.cc +++ b/src/lib/arch/riscv/Instruction_decode.cc @@ -157,29 +157,28 @@ void Instruction::decode() { sourceRegisterCount_++; } else { + /** + * Register writes to x0 are discarded so no destination register is + * set. + * + * While the execution stage may still write to the results array, + * when Instruction::getResults and + * Instruction::getDestinationRegisters are called during writeback, + * zero sized spans are returned (determined by the value of + * destinationRegisterCount). This in turn means no register update is + * performed. + * + * TODO this will break if there are more than 2 destination registers + * with one being the zero register e.g. if an instruction implicitly + * writes to a system register. The current implementation could mean + * that the second result is discarded + * + */ if (csRegToRegister(op.reg) != RegisterType::ZERO_REGISTER) { destinationRegisters_[destinationRegisterCount_] = csRegToRegister(op.reg); destinationRegisterCount_++; - } else { - /** - * Register writes to x0 are discarded so no destination register is - * set. - * - * While the execution stage may still write to the results array, - * when Instruction::getResults and - * Instruction::getDestinationRegisters are called during writeback, - * zero sized spans are returned (determined by the value of - * destinationRegisterCount). This in turn means no register update is - * performed. - * - * TODO this will break if there are more than 2 destination registers - * with one being the zero register e.g. if an instruction implicitly - * writes to a system register. The current implementation could mean - * that the second result is discarded - * - */ } } } else if (i > 0) { From ffbfc03680680ac950e430c3ad598058db03954d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 17:00:52 +0000 Subject: [PATCH 111/115] Add TODO --- test/unit/pipeline/FetchUnitTest.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index e640bdd343..d2c325eb6b 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -46,6 +46,7 @@ class PipelineFetchUnitTest protected: const uint8_t insnMinSizeBytes = GetParam().first; const uint8_t insnMaxSizeBytes = GetParam().second; + // TODO make this parameterisable and update all tests accordingly const uint8_t blockSize = 16; PipelineBuffer output; From f69eb0bba1c2cf28d14c13477bded0d9857f424d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 17:07:02 +0000 Subject: [PATCH 112/115] Comment update --- test/unit/pipeline/FetchUnitTest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index d2c325eb6b..acb95c712d 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -536,7 +536,7 @@ TEST_P(PipelineFetchUnitTest, invalidMinBytesAtEndOfBuffer) { .WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - // Buffer will contain invalid 2 bytes so predecode returns 0 bytes read + // Buffer will contain invalid min bytes so predecode returns 0 bytes read ON_CALL(isa, predecode(_, insnMinSizeBytes, 0x10 - insnMinSizeBytes, _)) .WillByDefault(Return(0)); From eca236162d51cfbd9b67a491eb679c150be0e87c Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 17:42:40 +0000 Subject: [PATCH 113/115] Clang format --- src/include/simeng/arch/aarch64/Instruction.hh | 4 ++-- src/include/simeng/arch/riscv/Instruction.hh | 4 ++-- src/lib/arch/riscv/Instruction_address.cc | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 2920f0d8ba..315a555a00 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -437,8 +437,8 @@ class Instruction : public simeng::Instruction { /** The current exception state of this instruction. */ InstructionException exception_ = InstructionException::None; - /** The number of source operands that have not yet had values supplied. Used to - * determine execution readiness. */ + /** The number of source operands that have not yet had values supplied. Used + * to determine execution readiness. */ uint16_t sourceOperandsPending_ = 0; /** Is the micro-operation opcode of the instruction, where appropriate. */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index 27499c90a4..888900ba18 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -244,8 +244,8 @@ class Instruction : public simeng::Instruction { /** The current exception state of this instruction. */ InstructionException exception_ = InstructionException::None; - /** The number of source operands that have not yet had values supplied. Used to - * determine execution readiness. */ + /** The number of source operands that have not yet had values supplied. Used + * to determine execution readiness. */ uint16_t sourceOperandsPending_ = 0; /** Used to denote what type of instruction this is. Utilises the constants in diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index c97779b45b..3a9fce30ff 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -21,14 +21,16 @@ span Instruction::generateAddresses() { "metadata_ operand not of correct type during RISC-V address " "generation"); address = sourceValues_[1].get(); - } else if (isInstruction(InsnType::isLoad) && isInstruction(InsnType::isAtomic)) { + } else if (isInstruction(InsnType::isLoad) && + isInstruction(InsnType::isAtomic)) { // Load reserved // Metadata operands[1] corresponds to instruction sourceRegValues[0] assert(metadata_.operands[1].type == RISCV_OP_REG && "metadata_ operand not of correct type during RISC-V address " "generation"); address = sourceValues_[0].get(); - } else if (isInstruction(InsnType::isStore) && isInstruction(InsnType::isAtomic)) { + } else if (isInstruction(InsnType::isStore) && + isInstruction(InsnType::isAtomic)) { // Store conditional assert(metadata_.operands[2].type == RISCV_OP_REG && "metadata_ operand not of correct type during RISC-V address " From 5827c891f4c43c22787f14a0f0c66bd396c273f8 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 18:01:14 +0000 Subject: [PATCH 114/115] Make compressed default false and update tests --- src/lib/config/ModelConfig.cc | 2 +- test/regression/riscv/instructions/compressed.cc | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index dc4bdacc58..197ed6ea4f 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -274,7 +274,7 @@ void ModelConfig::setExpectations(bool isDefault) { if (isa_ == ISA::RV64) { expectations_["Core"].addChild( - ExpectationNode::createExpectation(true, "Compressed")); + ExpectationNode::createExpectation(false, "Compressed")); expectations_["Core"]["Compressed"].setValueSet(std::vector{false, true}); } diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index c1f346ed3a..4b68edb76f 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -719,8 +719,9 @@ TEST_P(InstCompressed, ebreak) { EXPECT_EQ(stdout_.substr(0, sizeof(err1) - 1), err1); } -INSTANTIATE_TEST_SUITE_P(RISCV, InstCompressed, - ::testing::Values(std::make_tuple(EMULATION, "{}")), - paramToString); +INSTANTIATE_TEST_SUITE_P( + RISCV, InstCompressed, + ::testing::Values(std::make_tuple(EMULATION, "{Core: {Compressed: True}}")), + paramToString); } // namespace From bcb2490455503ba2467231a53019d5c8d5e57c5b Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Feb 2024 19:55:50 +0000 Subject: [PATCH 115/115] Change assertion to expect --- test/unit/pipeline/FetchUnitTest.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index acb95c712d..8ecdc7d88b 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -110,7 +110,9 @@ TEST_P(PipelineFetchUnitTest, FetchUnaligned) { ON_CALL(isa, getMinInstructionSize()).WillByDefault(Return(insnMinSizeBytes)); ON_CALL(memory, getCompletedReads()).WillByDefault(Return(completedReads)); - assert(insnMinSizeBytes > 1 && "min insn size too small to set PC correctly"); + // Min instruction size needs to be more than 1 to set PC correctly for this + // test + EXPECT_GT(insnMinSizeBytes, 1); uint64_t setPC = (blockSize - insnMinSizeBytes) + 1; // Set PC so that there will not be enough data to start decoding EXPECT_CALL(isa, predecode(_, _, _, _)).Times(0);