From 60d1b36e9ac8c8cda381266586be696de7c09ec5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 28 Feb 2024 10:25:14 -0500 Subject: [PATCH] Implement registers side. --- InstructionSets/ARM/Registers.hpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/InstructionSets/ARM/Registers.hpp b/InstructionSets/ARM/Registers.hpp index fc6718fd2..828a1b272 100644 --- a/InstructionSets/ARM/Registers.hpp +++ b/InstructionSets/ARM/Registers.hpp @@ -37,6 +37,10 @@ enum class Mode { /// Combines the ARM registers and status flags into a single whole, given that the architecture /// doesn't have the same degree of separation as others. +/// +/// The PC contained here is always taken to be **the address of the current instruction**, +/// i.e. disregarding pipeline differences. Appropriate prefetch offsets are left to other code to handle. +/// This is to try to keep this structure independent of a specific ARM implementation. struct Registers { public: /// Sets the N and Z flags according to the value of @c result. @@ -74,13 +78,28 @@ struct Registers { interrupt_flags_; } - void set_status(uint32_t) { + /// Sets status bits only, subject to mode. + void set_status(uint32_t status) { // ... in user mode the other flags (I, F, M1, M0) are protected from direct change // but in non-user modes these will also be affected, accepting copies of bits 27, 26, // 1 and 0 of the result respectively. + + negative_flag_ = status; + overflow_flag_ = status << 3; + carry_flag_ = status & ConditionCode::Carry; + zero_result_ = ~status & ConditionCode::Zero; + + if(mode_ != Mode::User) { + mode_ = Mode(status & 3); + interrupt_flags_ = status & (ConditionCode::IRQDisable | ConditionCode::FIQDisable); + } } - void set_pc(uint32_t) {} + /// Sets a new PC. + /// TODO: communicate this onward. + void set_pc(uint32_t value) { + active[15] = value & ConditionCode::Address; + } uint32_t pc(uint32_t offset) const { return (active[15] + offset) & ConditionCode::Address;