From 230e9c63273346f7286aa32f263005c1d27c483e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 3 Mar 2024 21:43:30 -0500 Subject: [PATCH] Obscure `active`. --- InstructionSets/ARM/Executor.hpp | 38 ++++++++-------- InstructionSets/ARM/Registers.hpp | 45 +++++++++++-------- .../Mac/Clock SignalTests/ARMDecoderTests.mm | 2 +- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/InstructionSets/ARM/Executor.hpp b/InstructionSets/ARM/Executor.hpp index 0650371b2..e03c236b1 100644 --- a/InstructionSets/ARM/Executor.hpp +++ b/InstructionSets/ARM/Executor.hpp @@ -36,7 +36,7 @@ struct Executor { if(fields.operand2() == 15) { operand2 = registers_.pc_status(pc_offset); } else { - operand2 = registers_.active[fields.operand2()]; + operand2 = registers_[fields.operand2()]; } uint32_t shift_amount; @@ -50,7 +50,7 @@ struct Executor { shift_amount = fields.shift_register() == 15 ? registers_.pc(4) : - registers_.active[fields.shift_register()]; + registers_[fields.shift_register()]; // A register shift amount of 0 has a different meaning than an in-instruction // shift amount of 0. @@ -74,7 +74,7 @@ struct Executor { // Write a raw result into the PC proxy if the target is R15; it'll be stored properly later. uint32_t pc_proxy = 0; - auto &destination = fields.destination() == 15 ? pc_proxy : registers_.active[fields.destination()]; + auto &destination = fields.destination() == 15 ? pc_proxy : registers_[fields.destination()]; // "When R15 appears in either of the Rn or Rs positions it will give the value // of the PC alone, with the PSR bits replaced by zeroes. ... @@ -85,7 +85,7 @@ struct Executor { const uint32_t operand1 = (fields.operand1() == 15) ? registers_.pc(shift_by_register ? 8 : 4) : - registers_.active[fields.operand1()]; + registers_[fields.operand1()]; uint32_t operand2; uint32_t rotate_carry = registers_.c(); @@ -216,11 +216,11 @@ struct Executor { // * Rn: with PSR, 8 bytes ahead; // * Rm: with PSR, 12 bytes ahead. - const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(4) : registers_.active[fields.multiplicand()]; - const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(4) : registers_.active[fields.multiplier()]; + const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(4) : registers_[fields.multiplicand()]; + const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(4) : registers_[fields.multiplier()]; const uint32_t accumulator = flags.operation() == MultiplyFlags::Operation::MUL ? 0 : - (fields.multiplicand() == 15 ? registers_.pc_status(8) : registers_.active[fields.accumulator()]); + (fields.multiplicand() == 15 ? registers_.pc_status(8) : registers_[fields.accumulator()]); const uint32_t result = multiplicand * multiplier + accumulator; @@ -230,7 +230,7 @@ struct Executor { } if(fields.destination() != 15) { - registers_.active[fields.destination()] = result; + registers_[fields.destination()] = result; } } @@ -238,7 +238,7 @@ struct Executor { constexpr BranchFlags flags(f); if constexpr (flags.operation() == BranchFlags::Operation::BL) { - registers_.active[14] = registers_.pc(0); + registers_[14] = registers_.pc(0); } registers_.set_pc(registers_.pc(4) + branch.offset()); } @@ -262,7 +262,7 @@ struct Executor { uint32_t address = transfer.base() == 15 ? registers_.pc(4) : - registers_.active[transfer.base()]; + registers_[transfer.base()]; // Determine what the address will be after offsetting. uint32_t offsetted_address = address; @@ -288,7 +288,7 @@ struct Executor { const uint32_t source = transfer.source() == 15 ? registers_.pc_status(8) : - registers_.active[transfer.source()]; + registers_[transfer.source()]; bool did_write; if constexpr (flags.transfer_byte()) { @@ -331,7 +331,7 @@ struct Executor { if(transfer.destination() == 15) { registers_.set_pc(value); } else { - registers_.active[transfer.destination()] = value; + registers_[transfer.destination()] = value; } } @@ -340,7 +340,7 @@ struct Executor { if(transfer.base() == 15) { registers_.set_pc(offsetted_address); } else { - registers_.active[transfer.base()] = offsetted_address; + registers_[transfer.base()] = offsetted_address; } } } @@ -355,7 +355,7 @@ struct Executor { // the final address if the base register is first in the write-out list. uint32_t address = transfer.base() == 15 ? registers_.pc_status(4) : - registers_.active[transfer.base()]; + registers_[transfer.base()]; const uint32_t initial_address = address; // Figure out what the final address will be, since that's what'll be @@ -449,9 +449,9 @@ struct Executor { // Also restore the base register. if(transfer.base() != 15) { if constexpr (flags.write_back_address()) { - registers_.active[transfer.base()] = final_address; + registers_[transfer.base()] = final_address; } else { - registers_.active[transfer.base()] = initial_address; + registers_[transfer.base()] = initial_address; } } } @@ -476,14 +476,14 @@ struct Executor { // Write out registers 1 to 14. for(int c = 0; c < 15; c++) { if(list & (1 << c)) { - access(registers_.active[c]); + access(registers_[c]); // Modify base register after each write if writeback is enabled. // This'll ensure the unmodified value goes out if it was the // first-selected register only. if constexpr (flags.write_back_address()) { if(transfer.base() != 15) { - registers_.active[transfer.base()] = final_address; + registers_[transfer.base()] = final_address; } } } @@ -493,7 +493,7 @@ struct Executor { // was empty. if constexpr (flags.write_back_address()) { if(transfer.base() != 15) { - registers_.active[transfer.base()] = final_address; + registers_[transfer.base()] = final_address; } } diff --git a/InstructionSets/ARM/Registers.hpp b/InstructionSets/ARM/Registers.hpp index a39c39228..a2c410268 100644 --- a/InstructionSets/ARM/Registers.hpp +++ b/InstructionSets/ARM/Registers.hpp @@ -80,7 +80,7 @@ struct Registers { /// @returns The full PC + status bits. uint32_t pc_status(uint32_t offset) const { return - ((active[15] + offset) & ConditionCode::Address) | + ((active_[15] + offset) & ConditionCode::Address) | status(); } @@ -108,12 +108,12 @@ struct Registers { /// Sets a new PC. void set_pc(uint32_t value) { - active[15] = value & ConditionCode::Address; + active_[15] = value & ConditionCode::Address; } /// @returns The stored PC plus @c offset limited to 26 bits. uint32_t pc(uint32_t offset) const { - return (active[15] + offset) & ConditionCode::Address; + return (active_[15] + offset) & ConditionCode::Address; } // MARK: - Exceptions. @@ -150,15 +150,15 @@ struct Registers { switch(exception) { case Exception::IRQ: set_mode(Mode::IRQ); - active[14] = pc(8); + active_[14] = pc(8); break; case Exception::FIQ: set_mode(Mode::FIQ); - active[14] = pc(8); + active_[14] = pc(8); break; default: set_mode(Mode::Supervisor); - active[14] = pc(4); + active_[14] = pc(4); break; } @@ -223,16 +223,16 @@ struct Registers { // if the incoming mode is FIQ then the other five will be saved in the next switch. switch(mode_) { case Mode::FIQ: - std::copy(active.begin() + 8, active.begin() + 15, fiq_registers_.begin()); + std::copy(active_.begin() + 8, active_.begin() + 15, fiq_registers_.begin()); break; case Mode::User: - std::copy(active.begin() + 13, active.begin() + 15, user_registers_.begin() + 5); + std::copy(active_.begin() + 13, active_.begin() + 15, user_registers_.begin() + 5); break; case Mode::Supervisor: - std::copy(active.begin() + 13, active.begin() + 15, supervisor_registers_.begin()); + std::copy(active_.begin() + 13, active_.begin() + 15, supervisor_registers_.begin()); break; case Mode::IRQ: - std::copy(active.begin() + 13, active.begin() + 15, irq_registers_.begin()); + std::copy(active_.begin() + 13, active_.begin() + 15, irq_registers_.begin()); break; } @@ -240,31 +240,35 @@ struct Registers { // For FIQ: save an additional five, then overwrite seven. switch(target_mode) { case Mode::FIQ: - std::copy(active.begin() + 8, active.begin() + 13, user_registers_.begin()); - std::copy(fiq_registers_.begin(), fiq_registers_.end(), active.begin() + 8); + std::copy(active_.begin() + 8, active_.begin() + 13, user_registers_.begin()); + std::copy(fiq_registers_.begin(), fiq_registers_.end(), active_.begin() + 8); break; case Mode::User: - std::copy(user_registers_.begin() + 5, user_registers_.end(), active.begin() + 13); + std::copy(user_registers_.begin() + 5, user_registers_.end(), active_.begin() + 13); break; case Mode::Supervisor: - std::copy(supervisor_registers_.begin(), supervisor_registers_.end(), active.begin() + 13); + std::copy(supervisor_registers_.begin(), supervisor_registers_.end(), active_.begin() + 13); break; case Mode::IRQ: - std::copy(irq_registers_.begin(), irq_registers_.end(), active.begin() + 13); + std::copy(irq_registers_.begin(), irq_registers_.end(), active_.begin() + 13); break; } // If FIQ is outgoing then there's another five registers to restore. if(mode_ == Mode::FIQ) { - std::copy(user_registers_.begin(), user_registers_.begin() + 5, active.begin() + 8); + std::copy(user_registers_.begin(), user_registers_.begin() + 5, active_.begin() + 8); } mode_ = target_mode; } - /// The active register set. TODO: switch to an implementation of operator[], hiding the - /// current implementation decision to maintain this as a linear block of memory. - std::array active{}; + uint32_t &operator[](int offset) { + return active_[offset]; + } + + const uint32_t operator[](int offset) const { + return active_[offset]; + } private: Mode mode_ = Mode::Supervisor; @@ -280,6 +284,9 @@ struct Registers { std::array fiq_registers_{}; std::array irq_registers_{}; std::array supervisor_registers_{}; + + // The active register set. + std::array active_{}; }; } diff --git a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm index 576979694..499a4f7a4 100644 --- a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm @@ -225,7 +225,7 @@ struct Memory { // // printf("%08x: %08x [", executor->pc(), instruction); // for(int c = 0; c < 15; c++) { -// printf("r%d:%08x ", c, executor->registers().active[c]); +// printf("r%d:%08x ", c, executor->registers()[c]); // } // printf("psr:%08x]\n", executor->registers().status()); // execute(instruction, *executor);