diff --git a/OSBindings/Mac/Clock SignalTests/6809Tests.mm b/OSBindings/Mac/Clock SignalTests/6809Tests.mm index 7bc3454cd..83303ea03 100644 --- a/OSBindings/Mac/Clock SignalTests/6809Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/6809Tests.mm @@ -283,4 +283,18 @@ struct M6809Traits { } } +- (void)testIndexer { + using IndexedAddressDecoder = CPU::M6809::IndexedAddressDecoder; + IndexedAddressDecoder decoder; + + decoder = IndexedAddressDecoder(0x00); + XCTAssertEqual(decoder.required_continuation(), 0); + for(int c = 0; c < 65536; c += 13) { + CPU::M6809::Registers regs; + regs.x = c; + XCTAssertEqual(decoder.address(regs), c); + XCTAssertEqual(regs.x, c + 1); + } +} + @end diff --git a/Processors/6809/6809.hpp b/Processors/6809/6809.hpp index 26192fafd..32ceb443e 100644 --- a/Processors/6809/6809.hpp +++ b/Processors/6809/6809.hpp @@ -315,7 +315,6 @@ struct Processor { // TODO: test interrupts and more. } -// printf("--- Fetch\n"); read(BusState::Normal, Literal(registers_.pc.full), opcode, ++registers_.pc.full); { operation_ = Reflection::dispatch(op_mapper0, opcode, op_returner); @@ -776,5 +775,4 @@ private: IndexedAddressDecoder indexer_; uint16_t *stack_ = nullptr; }; - } diff --git a/Processors/6809/Registers.hpp b/Processors/6809/Registers.hpp index 0e6b07281..dc4dcc20b 100644 --- a/Processors/6809/Registers.hpp +++ b/Processors/6809/Registers.hpp @@ -203,18 +203,13 @@ struct Registers { default: __builtin_unreachable(); } } - - /// @returns The value of DP as the high byte of an address. - uint16_t dp_high() const { - return uint16_t(dp << 8); // TODO: worth precomputing? - } }; struct IndexedAddressDecoder { IndexedAddressDecoder() = default; constexpr IndexedAddressDecoder(const uint8_t format) noexcept : format_(format) {} - enum FormSuffix: uint8_t { + enum class FormSuffix { NoOffset = 0b0100, Offset8bit = 0b1000, @@ -226,17 +221,30 @@ struct IndexedAddressDecoder { BRegisterOffset = 0b0101, DRegisterOffset = 0b1011, - PostincrementBy1 = 0b1000, + PostincrementBy1 = 0b0000, PostincrementBy2 = 0b0001, PredecrementBy1 = 0b0010, PredecrementBy2 = 0b0011, }; static constexpr uint8_t ExtendedIndirect = 0x9f; - int required_continuation() const { - if(!(format_ & 0x80)) return 0; + constexpr FormSuffix suffix() const { + return FormSuffix(format_ & 0b1111); + } + constexpr bool is_5bit() const { + return !(format_ & 0xb1000'0000); + } + constexpr bool indirect() const { + return + suffix() != FormSuffix::PostincrementBy1 && + suffix() != FormSuffix::PredecrementBy1 && + (format_ & 0b1001'0000) == 0b1001'0000; + } + + constexpr int required_continuation() const { + if(is_5bit()) return 0; if(format_ == ExtendedIndirect) return 2; - switch(format_ & 0b1111) { + switch(suffix()) { using enum FormSuffix; case Offset8bit: case Offset8bitFromPC: return 1; case Offset16bit: case Offset16bitFromPC: return 2; @@ -257,32 +265,33 @@ struct IndexedAddressDecoder { return continuation_; } + const auto reg = [&] () -> uint16_t & { + switch((format_ >> 5) & 0b11) { + case 0b00: return registers.reg(); + case 0b01: return registers.reg(); + case 0b10: return registers.reg(); + case 0b11: return registers.reg(); + default: __builtin_unreachable(); + } + }; + const uint16_t base = [&] { + if(is_5bit()) { + return reg(); + } + if( - (format_ & 0x80) && + !is_5bit() && ( - ((format_ & 0b1111) == FormSuffix::Offset8bitFromPC) || - ((format_ & 0b1111) == FormSuffix::Offset16bitFromPC) + (suffix() == FormSuffix::Offset8bitFromPC) || + (suffix() == FormSuffix::Offset16bitFromPC) ) ) { return registers.reg(); } - auto reg = [&] () -> uint16_t & { - switch((format_ >> 5) & 3) { - case 0b00: return registers.reg(); - case 0b01: return registers.reg(); - case 0b10: return registers.reg(); - case 0b11: return registers.reg(); - default: __builtin_unreachable(); - } - }; - - if(!(format_ & 0x80)) { - return reg(); - } - - switch(format_ & 0b1111) { + switch(suffix()) { + using enum FormSuffix; default: return reg(); case PredecrementBy2: @@ -308,13 +317,13 @@ struct IndexedAddressDecoder { } (); // A high bit of 0 implies the low five bits are the offset. - if(!(format_ & 0x80)) { + if(is_5bit()) { // Shift sign bit up to bit 7 and convert to int8_t to effect it. // Then shift back down to get the correct value. return uint16_t(base + (int8_t(format_ << 3) >> 3)); } - switch(format_ & 0b1111) { + switch(suffix()) { using enum FormSuffix; default: return base; @@ -332,10 +341,6 @@ struct IndexedAddressDecoder { return base; } - bool indirect() const { - return (format_ & 0x90) == 0x90; - } - private: uint8_t format_; uint16_t continuation_ = 0;