diff --git a/InstructionSets/ARM/Registers.hpp b/InstructionSets/ARM/Registers.hpp index 4de1f01d1..8d27026c5 100644 --- a/InstructionSets/ARM/Registers.hpp +++ b/InstructionSets/ARM/Registers.hpp @@ -93,6 +93,10 @@ struct Registers { } } + Mode mode() { + return mode_; + } + /// Sets a new PC. /// TODO: communicate this onward. void set_pc(uint32_t value) { diff --git a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm index 9af05bf35..960e41703 100644 --- a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm @@ -17,6 +17,27 @@ using namespace InstructionSet::ARM; namespace { +struct Memory { + template + bool write(uint32_t address, IntT source, Mode mode, bool trans) { + (void)address; + (void)source; + (void)mode; + (void)trans; + return true; + } + + template + bool read(uint32_t address, IntT &source, Mode mode, bool trans) { + (void)address; + (void)source; + (void)mode; + (void)trans; + return true; + } +}; + +template struct Scheduler { bool should_schedule(Condition condition) { return registers_.test(condition); @@ -269,12 +290,53 @@ struct Scheduler { address = offsetted_address; } - // TODO: attempt access, possibly abort. - // Cf. transfer_byte() + constexpr bool trans = !flags.pre_index() && flags.write_back_address(); + if constexpr (flags.operation() == SingleDataTransferFlags::Operation::STR) { + const uint32_t source = + transfer.source() == 15 ? + registers_.pc_status(12) : + registers_.active[transfer.source()]; + + bool did_write; + if constexpr (flags.transfer_byte()) { + did_write = bus_.template write(address, uint8_t(source), registers_.mode(), trans); + } else { + did_write = bus_.template write(address, source, registers_.mode(), trans); + } + + if(!did_write) { + registers_.exception(); + return; + } + } else { + bool did_read; + uint32_t value; + + if constexpr (flags.transfer_byte()) { + uint8_t target; + did_read = bus_.template read(address, target, registers_.mode(), trans); + value = target; + } else { + did_read = bus_.template read(address, value, registers_.mode(), trans); + + // TODO: "An address offset from a word boundary will cause the data to be rotated into the + // register so that the addressed byte occuplies bits 0 to 7. + } + + if(!did_read) { + registers_.exception(); + return; + } + + if(transfer.destination() == 15) { + registers_.set_pc(value); + } else { + registers_.active[transfer.destination()] = value; + } + } // If either postindexing or else with writeback, update base. if constexpr (!flags.pre_index() || flags.write_back_address()) { - // TODO: check for R15. if(transfer.base() == 15) { registers_.set_pc(offsetted_address); } else { @@ -302,6 +364,8 @@ struct Scheduler { registers_.exception(); } + MemoryT bus_; + private: Registers registers_; }; @@ -314,7 +378,7 @@ private: @implementation ARMDecoderTests - (void)testXYX { - Scheduler scheduler; + Scheduler scheduler; for(int c = 0; c < 65536; c++) { InstructionSet::ARM::dispatch(c << 16, scheduler);