diff --git a/InstructionSets/ARM/Registers.hpp b/InstructionSets/ARM/Registers.hpp index b08567272..036c77b1c 100644 --- a/InstructionSets/ARM/Registers.hpp +++ b/InstructionSets/ARM/Registers.hpp @@ -342,6 +342,33 @@ struct Registers { return active_[static_cast(offset)]; } + /// @returns A reference to the register at @c offset. If @c force_user_mode is true, + /// this will the the user-mode register. Otherwise it'll be that for the current mode. These references + /// are guaranteed to remain valid only until the next mode change. + template + uint32_t ®(uint32_t offset) { + if constexpr (!force_user_mode) { + return active_[offset]; + } + + switch(mode_) { + case Mode::User: return active_[offset]; + + case Mode::Supervisor: + case Mode::IRQ: + if(offset == 13 || offset == 14) { + return user_registers_[offset - 8]; + } + return active_[offset]; + + case Mode::FIQ: + if(offset >= 8 && offset < 15) { + return user_registers_[offset - 8]; + } + return active_[offset]; + } + } + private: Mode mode_ = Mode::Supervisor;