Make *ie and *ip registers 64 bit CSRs. Fixes an issue in a test where a shift of 32 was performed on a 32 bit quantity (undefined behavior in C++) PiperOrigin-RevId: 823071750 Change-Id: I56afa96530b536d273aa7c8dd2e4e80fe9112c5f
diff --git a/riscv/riscv_xip_xie.cc b/riscv/riscv_xip_xie.cc index 608c7c1..9c92d9a 100644 --- a/riscv/riscv_xip_xie.cc +++ b/riscv/riscv_xip_xie.cc
@@ -24,78 +24,77 @@ namespace riscv { // Machine Interrupt Pending methods. -RiscVMIp::RiscVMIp(uint32_t initial_value, ArchState* state) - : RiscVSimpleCsr<uint32_t>("mip", RiscVCsrEnum::kMIp, initial_value, +RiscVMIp::RiscVMIp(uint64_t initial_value, ArchState* state) + : RiscVSimpleCsr<uint64_t>("mip", RiscVCsrEnum::kMIp, initial_value, kReadMask, kWriteMask, state) {} -void RiscVMIp::Set(uint32_t value) { - this->RiscVSimpleCsr<uint32_t>::Set(value); +void RiscVMIp::Set(uint64_t value) { + this->RiscVSimpleCsr<uint64_t>::Set(value); if (value != 0) { state()->CheckForInterrupt(); } } -void RiscVMIp::Set(uint64_t value) { Set(static_cast<uint32_t>(value)); } +void RiscVMIp::Set(uint32_t value) { Set(static_cast<uint64_t>(value)); } -uint32_t RiscVMIp::GetUint32() { - return this->RiscVSimpleCsr<uint32_t>::GetUint32() | ext_seip_; +uint32_t RiscVMIp::GetUint32() { return static_cast<uint32_t>(GetUint64()); } + +uint64_t RiscVMIp::GetUint64() { + return this->RiscVSimpleCsr<uint64_t>::GetUint64() | ext_seip_; } -uint64_t RiscVMIp::GetUint64() { return GetUint32(); } - // Supervisor Interrupt Pending methods. RiscVSIp::RiscVSIp(RiscVMIp* mip, RiscVCsrInterface* mideleg, ArchState* state) - : RiscVSimpleCsr<uint32_t>("sip", RiscVCsrEnum::kSIp, kReadMask, kWriteMask, + : RiscVSimpleCsr<uint64_t>("sip", RiscVCsrEnum::kSIp, kReadMask, kWriteMask, state), mip_(mip), mideleg_(mideleg) {} -void RiscVSIp::Set(uint32_t value) { - auto wmask = write_mask() | mideleg_->GetUint32(); - mip_->Set((mip_->GetUint32() & wmask) | (value & wmask)); +void RiscVSIp::Set(uint64_t value) { + auto wmask = write_mask() | mideleg_->GetUint64(); + mip_->Set((mip_->GetUint64() & wmask) | (value & wmask)); } -void RiscVSIp::Set(uint64_t value) { Set(static_cast<uint32_t>(value)); } +void RiscVSIp::Set(uint32_t value) { Set(static_cast<uint64_t>(value)); } // Machine Interrupt Enable methods. -RiscVMIe::RiscVMIe(uint32_t initial_value, ArchState* state) - : RiscVSimpleCsr<uint32_t>("mie", RiscVCsrEnum::kMIe, initial_value, +RiscVMIe::RiscVMIe(uint64_t initial_value, ArchState* state) + : RiscVSimpleCsr<uint64_t>("mie", RiscVCsrEnum::kMIe, initial_value, kReadMask, kWriteMask, state) {} -void RiscVMIe::Set(uint32_t value) { - this->RiscVSimpleCsr<uint32_t>::Set(value); + +void RiscVMIe::Set(uint32_t value) { Set(static_cast<uint64_t>(value)); } + +void RiscVMIe::Set(uint64_t value) { + this->RiscVSimpleCsr<uint64_t>::Set(value); if (value != 0) { state()->CheckForInterrupt(); } } -uint32_t RiscVSIp::GetUint32() { - return mip_->GetUint32() & (mideleg_->GetUint32() | read_mask()); +uint64_t RiscVSIp::GetUint64() { + return mip_->GetUint64() & (mideleg_->GetUint64() | read_mask()); } -uint64_t RiscVSIp::GetUint64() { return GetUint32(); } - -void RiscVMIe::Set(uint64_t value) { - this->RiscVSimpleCsr<uint32_t>::Set(value); -} +uint32_t RiscVSIp::GetUint32() { return static_cast<uint32_t>(GetUint64()); } // Supervisor Interrupt Enable methods. RiscVSIe::RiscVSIe(RiscVMIe* mie, RiscVCsrInterface* mideleg, ArchState* state) - : RiscVSimpleCsr<uint32_t>("sie", RiscVCsrEnum::kSIe, kReadMask, kWriteMask, + : RiscVSimpleCsr<uint64_t>("sie", RiscVCsrEnum::kSIe, kReadMask, kWriteMask, state), mie_(mie), mideleg_(mideleg) {} -void RiscVSIe::Set(uint32_t value) { - auto wmask = write_mask() | mideleg_->GetUint32(); - mie_->Set((mie_->GetUint32() & wmask) | (value & wmask)); +void RiscVSIe::Set(uint64_t value) { + auto wmask = write_mask() | mideleg_->GetUint64(); + mie_->Set((mie_->GetUint64() & wmask) | (value & wmask)); } -void RiscVSIe::Set(uint64_t value) { Set(static_cast<uint32_t>(value)); } +void RiscVSIe::Set(uint32_t value) { Set(static_cast<uint64_t>(value)); } -uint32_t RiscVSIe::GetUint32() { - return mie_->GetUint32() & (mideleg_->GetUint32() | read_mask()); +uint64_t RiscVSIe::GetUint64() { + return mie_->GetUint64() & (mideleg_->GetUint64() | read_mask()); } -uint64_t RiscVSIe::GetUint64() { return GetUint32(); } +uint32_t RiscVSIe::GetUint32() { return static_cast<uint32_t>(GetUint64()); } } // namespace riscv } // namespace sim
diff --git a/riscv/riscv_xip_xie.h b/riscv/riscv_xip_xie.h index 66b7b1e..5a23a74 100644 --- a/riscv/riscv_xip_xie.h +++ b/riscv/riscv_xip_xie.h
@@ -34,24 +34,24 @@ class MipExternalWriteInterface { public: virtual ~MipExternalWriteInterface() = default; - virtual void set_meip(uint32_t value) = 0; - virtual void set_mtip(uint32_t value) = 0; - virtual void set_msip(uint32_t value) = 0; - virtual void set_ext_seip(uint32_t value) = 0; + virtual void set_meip(uint64_t value) = 0; + virtual void set_mtip(uint64_t value) = 0; + virtual void set_msip(uint64_t value) = 0; + virtual void set_ext_seip(uint64_t value) = 0; }; // xip - x mode interrupt pending registers. class RiscVMIp : public MipExternalWriteInterface, - public RiscVSimpleCsr<uint32_t> { + public RiscVSimpleCsr<uint64_t> { public: // Read and Write masks. - static constexpr uint32_t kReadMask = 0b1011'1011'1011; - static constexpr uint32_t kWriteMask = 0b0011'0011'1011; + static constexpr uint64_t kReadMask = 0b1011'1011'1011; + static constexpr uint64_t kWriteMask = 0b0011'0011'1011; // Disable default constructor. RiscVMIp() = delete; - RiscVMIp(uint32_t initial_value, ArchState* state); + RiscVMIp(uint64_t initial_value, ArchState* state); ~RiscVMIp() override = default; // RiscVSimpleCsr method overrides. @@ -64,55 +64,55 @@ bool meip() { return GetterHelper<11, 0b1>(); } bool seip() { return (GetterHelper<9, 0b1>()) || (ext_seip_ != 0); } bool ueip() { return GetterHelper<8, 0b1>(); } - void set_meip(uint32_t value) override { SetterHelper<11, 0b1>(value); } - void set_seip(uint32_t value) { SetterHelper<9, 0b1>(value); } - void set_ext_seip(uint32_t value) override { ext_seip_ = (value != 0) << 9; } - void set_ueip(uint32_t value) { SetterHelper<8, 0b1>(value); } + void set_meip(uint64_t value) override { SetterHelper<11, 0b1>(value); } + void set_seip(uint64_t value) { SetterHelper<9, 0b1>(value); } + void set_ext_seip(uint64_t value) override { ext_seip_ = (value != 0) << 9; } + void set_ueip(uint64_t value) { SetterHelper<8, 0b1>(value); } // X timer interrupt pending. bool mtip() { return GetterHelper<7, 0b1>(); } bool stip() { return GetterHelper<5, 0b1>(); } bool utip() { return GetterHelper<4, 0b1>(); } - void set_mtip(uint32_t value) override { SetterHelper<7, 0b1>(value); } - void set_stip(uint32_t value) { SetterHelper<5, 0b1>(value); } - void set_utip(uint32_t value) { SetterHelper<4, 0b1>(value); } + void set_mtip(uint64_t value) override { SetterHelper<7, 0b1>(value); } + void set_stip(uint64_t value) { SetterHelper<5, 0b1>(value); } + void set_utip(uint64_t value) { SetterHelper<4, 0b1>(value); } // X software interrupt pending. bool msip() { return GetterHelper<3, 0b1>(); } bool ssip() { return GetterHelper<1, 0b1>(); } bool usip() { return GetterHelper<0, 0b1>(); } - void set_msip(uint32_t value) override { SetterHelper<3, 0b1>(value); } - void set_ssip(uint32_t value) { SetterHelper<1, 0b1>(value); } - void set_usip(uint32_t value) { SetterHelper<0, 0b1>(value); } + void set_msip(uint64_t value) override { SetterHelper<3, 0b1>(value); } + void set_ssip(uint64_t value) { SetterHelper<1, 0b1>(value); } + void set_usip(uint64_t value) { SetterHelper<0, 0b1>(value); } private: // Template function to help implement the getters. - template <int Shift, uint32_t BitMask> + template <int Shift, uint64_t BitMask> inline int GetterHelper() { - return (GetUint32() >> Shift) & BitMask; + return (GetUint64() >> Shift) & BitMask; } // Template function to help implement the setters. - template <int Shift, uint32_t BitMask> - inline void SetterHelper(uint32_t value) { + template <int Shift, uint64_t BitMask> + inline void SetterHelper(uint64_t value) { uint64_t bit_value = value & BitMask; uint64_t new_value = (GetUint64() & ~(BitMask << Shift)) | (bit_value << Shift); Set(new_value); } - uint32_t ext_seip_ = 0; + uint64_t ext_seip_ = 0; }; // The supervisor mode sip is an interface to mip. The visibility of mip bits // depends on the value of mideleg. Delegated interrupts bits are readable and // writable in sip as they would be in mip. -class RiscVSIp : public RiscVSimpleCsr<uint32_t> { +class RiscVSIp : public RiscVSimpleCsr<uint64_t> { public: // Read and Write masks. - static constexpr uint32_t kReadMask = 0b1011'1011'1011; - static constexpr uint32_t kWriteMask = 0b0011'0011'0011; - static constexpr uint32_t kMBitMask = 0b1000'1000'1000; - static constexpr uint32_t kSBitMask = 0b0010'0010'0010; - static constexpr uint32_t kUBitMask = 0b0001'0001'0001; + static constexpr uint64_t kReadMask = 0b1011'1011'1011; + static constexpr uint64_t kWriteMask = 0b0011'0011'0011; + static constexpr uint64_t kMBitMask = 0b1000'1000'1000; + static constexpr uint64_t kSBitMask = 0b0010'0010'0010; + static constexpr uint64_t kUBitMask = 0b0001'0001'0001; // Disable default constructor. RiscVSIp() = delete; @@ -127,34 +127,34 @@ // X external interrupt pending. bool meip() { - return mip_->meip() && (mideleg_->AsUint32() & 0b1000'0000'0000) != 0; + return mip_->meip() && (mideleg_->AsUint64() & 0b1000'0000'0000) != 0; } bool seip() { return mip_->seip(); } bool ueip() { return mip_->ueip(); } void set_meip(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000'0000'0000) != 0) mip_->set_meip(value); + if ((mideleg_->AsUint64() & 0b1000'0000'0000) != 0) mip_->set_meip(value); } void set_seip(uint32_t value) { mip_->set_seip(value); } void set_ueip(uint32_t value) { mip_->set_ueip(value); } // X timer interrupt pending. bool mtip() { - return mip_->mtip() && (mideleg_->AsUint32() & 0b1000'0000) != 0; + return mip_->mtip() && (mideleg_->AsUint64() & 0b1000'0000) != 0; } bool stip() { return mip_->stip(); } bool utip() { return mip_->utip(); } void set_mtip(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000'0000) != 0) mip_->set_mtip(value); + if ((mideleg_->AsUint64() & 0b1000'0000) != 0) mip_->set_mtip(value); } void set_stip(uint32_t value) { mip_->set_stip(value); } void set_utip(uint32_t value) { mip_->set_utip(value); } // X software interrupt pending. - bool msip() { return mip_->msip() && (mideleg_->AsUint32() & 0b1000) != 0; } + bool msip() { return mip_->msip() && (mideleg_->AsUint64() & 0b1000) != 0; } bool ssip() { return mip_->ssip(); } bool usip() { return mip_->usip(); } void set_msip(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000) != 0) mip_->set_msip(value); + if ((mideleg_->AsUint64() & 0b1000) != 0) mip_->set_msip(value); } void set_ssip(uint32_t value) { mip_->set_ssip(value); } void set_usip(uint32_t value) { mip_->set_usip(value); } @@ -166,15 +166,15 @@ // xie - x mode interrupt enable registers. -class RiscVMIe : public RiscVSimpleCsr<uint32_t> { +class RiscVMIe : public RiscVSimpleCsr<uint64_t> { public: // Read and Write masks. - static constexpr uint32_t kReadMask = 0b1011'1011'1011; - static constexpr uint32_t kWriteMask = 0b1011'1011'1011; + static constexpr uint64_t kReadMask = 0b1011'1011'1011; + static constexpr uint64_t kWriteMask = 0b1011'1011'1011; // Disable default constructor. RiscVMIe() = delete; - RiscVMIe(uint32_t initial_value, ArchState* state); + RiscVMIe(uint64_t initial_value, ArchState* state); ~RiscVMIe() override = default; // RiscVSimpleCsr method overrides. @@ -185,35 +185,35 @@ bool meie() { return GetterHelper<11, 0b1>(); } bool seie() { return GetterHelper<9, 0b1>(); } bool ueie() { return GetterHelper<8, 0b1>(); } - void set_meie(uint32_t value) { SetterHelper<11, 0b1>(value); } - void set_seie(uint32_t value) { SetterHelper<9, 0b1>(value); } - void set_ueie(uint32_t value) { SetterHelper<8, 0b1>(value); } + void set_meie(uint64_t value) { SetterHelper<11, 0b1>(value); } + void set_seie(uint64_t value) { SetterHelper<9, 0b1>(value); } + void set_ueie(uint64_t value) { SetterHelper<8, 0b1>(value); } // X timer interrupt pending. bool mtie() { return GetterHelper<7, 0b1>(); } bool stie() { return GetterHelper<5, 0b1>(); } bool utie() { return GetterHelper<4, 0b1>(); } - void set_mtie(uint32_t value) { SetterHelper<7, 0b1>(value); } - void set_stie(uint32_t value) { SetterHelper<5, 0b1>(value); } - void set_utie(uint32_t value) { SetterHelper<4, 0b1>(value); } + void set_mtie(uint64_t value) { SetterHelper<7, 0b1>(value); } + void set_stie(uint64_t value) { SetterHelper<5, 0b1>(value); } + void set_utie(uint64_t value) { SetterHelper<4, 0b1>(value); } // X software interrupt pending. bool msie() { return GetterHelper<3, 0b1>(); } bool ssie() { return GetterHelper<1, 0b1>(); } bool usie() { return GetterHelper<0, 0b1>(); } - void set_msie(uint32_t value) { SetterHelper<3, 0b1>(value); } - void set_ssie(uint32_t value) { SetterHelper<1, 0b1>(value); } - void set_usie(uint32_t value) { SetterHelper<0, 0b1>(value); } + void set_msie(uint64_t value) { SetterHelper<3, 0b1>(value); } + void set_ssie(uint64_t value) { SetterHelper<1, 0b1>(value); } + void set_usie(uint64_t value) { SetterHelper<0, 0b1>(value); } private: // Template function to help implement the getters. - template <int Shift, uint32_t BitMask> + template <int Shift, uint64_t BitMask> inline int GetterHelper() { - return (GetUint32() >> Shift) & BitMask; + return (GetUint64() >> Shift) & BitMask; } // Template function to help implement the setters. - template <int Shift, uint32_t BitMask> - inline void SetterHelper(uint32_t value) { + template <int Shift, uint64_t BitMask> + inline void SetterHelper(uint64_t value) { uint64_t bit_value = value & BitMask; uint64_t new_value = (GetUint64() & ~(BitMask << Shift)) | (bit_value << Shift); @@ -222,11 +222,11 @@ }; // The supervisor sie is an interface to the mie. -class RiscVSIe : public RiscVSimpleCsr<uint32_t> { +class RiscVSIe : public RiscVSimpleCsr<uint64_t> { public: // Read and Write masks. - static constexpr uint32_t kReadMask = 0b1011'1011'1011; - static constexpr uint32_t kWriteMask = 0b1011'1011'1011; + static constexpr uint64_t kReadMask = 0b1011'1011'1011; + static constexpr uint64_t kWriteMask = 0b1011'1011'1011; // Disable default constructor. RiscVSIe() = delete; @@ -241,37 +241,37 @@ // X external interrupt pending. bool meie() { - return mie_->meie() && (mideleg_->AsUint32() & 0b1000'0000'0000) != 0; + return mie_->meie() && (mideleg_->AsUint64() & 0b1000'0000'0000) != 0; } bool seie() { return mie_->seie(); } bool ueie() { return mie_->ueie(); } - void set_meie(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000'0000'0000) != 0) mie_->set_meie(value); + void set_meie(uint64_t value) { + if ((mideleg_->AsUint64() & 0b1000'0000'0000) != 0) mie_->set_meie(value); } - void set_seie(uint32_t value) { mie_->set_seie(value); } - void set_ueie(uint32_t value) { mie_->set_ueie(value); } + void set_seie(uint64_t value) { mie_->set_seie(value); } + void set_ueie(uint64_t value) { mie_->set_ueie(value); } // X timer interrupt pending. bool mtie() { - return mie_->mtie() && (mideleg_->AsUint32() & 0b1000'0000) != 0; + return mie_->mtie() && (mideleg_->AsUint64() & 0b1000'0000) != 0; } bool stie() { return mie_->stie(); } bool utie() { return mie_->utie(); } - void set_mtie(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000'0000) != 0) mie_->set_mtie(value); + void set_mtie(uint64_t value) { + if ((mideleg_->AsUint64() & 0b1000'0000) != 0) mie_->set_mtie(value); } - void set_stie(uint32_t value) { mie_->set_stie(value); } - void set_utie(uint32_t value) { mie_->set_utie(value); } + void set_stie(uint64_t value) { mie_->set_stie(value); } + void set_utie(uint64_t value) { mie_->set_utie(value); } // X software interrupt pending. - bool msie() { return mie_->msie() && (mideleg_->AsUint32() & 0b1000) != 0; } + bool msie() { return mie_->msie() && (mideleg_->AsUint64() & 0b1000) != 0; } bool ssie() { return mie_->ssie(); } bool usie() { return mie_->usie(); } - void set_msie(uint32_t value) { - if ((mideleg_->AsUint32() & 0b1000) != 0) mie_->set_msie(value); + void set_msie(uint64_t value) { + if ((mideleg_->AsUint64() & 0b1000) != 0) mie_->set_msie(value); } - void set_ssie(uint32_t value) { mie_->set_ssie(value); } - void set_usie(uint32_t value) { mie_->set_usie(value); } + void set_ssie(uint64_t value) { mie_->set_ssie(value); } + void set_usie(uint64_t value) { mie_->set_usie(value); } private: RiscVMIe* mie_;
diff --git a/riscv/test/riscv32_bitmanip_instructions_test.cc b/riscv/test/riscv32_bitmanip_instructions_test.cc index a7737b0..a679ba3 100644 --- a/riscv/test/riscv32_bitmanip_instructions_test.cc +++ b/riscv/test/riscv32_bitmanip_instructions_test.cc
@@ -538,7 +538,7 @@ T val1 = absl::Uniform(absl::IntervalClosed, bitgen_, std::numeric_limits<T>::min(), std::numeric_limits<T>::max()); - T val2 = absl::Uniform(absl::IntervalClosed, bitgen_, 0, 32); + T val2 = absl::Uniform(absl::IntervalClosed, bitgen_, 0, 31); SetRegisterValues<uint32_t>({{kX1, val1}, {kX2, val2}}); instruction_->Execute(nullptr); EXPECT_EQ(GetRegisterValue<uint32_t>(kX3), val1 | (1 << val2));