From c070f2100c55c5e23b5854d134f0123aa734e286 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 1 Nov 2019 23:01:06 -0400 Subject: [PATCH] Attempts to regularise data bus access. --- Machines/AtariST/AtariST.cpp | 77 +++---------------- Machines/AtariST/Video.cpp | 20 ++--- Machines/AtariST/Video.hpp | 4 +- Processors/68000/68000.hpp | 69 +++++++++++++++++ .../Implementation/68000Implementation.hpp | 7 +- 5 files changed, 99 insertions(+), 78 deletions(-) diff --git a/Machines/AtariST/AtariST.cpp b/Machines/AtariST/AtariST.cpp index 513f7479a..d7a9bbd1b 100644 --- a/Machines/AtariST/AtariST.cpp +++ b/Machines/AtariST/AtariST.cpp @@ -398,23 +398,21 @@ class ConcreteMachine: case 0x7fc401: /* PSG: write to write register. */ if(!cycle.data_select_active()) return HalfCycles(0); - // TODO: byte accesses to the odd addresses shouldn't obey logic below. advance_time(HalfCycles(2)); update_audio(); + if(cycle.operation & Microcycle::Read) { ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BC1)); - cycle.value->halves.low = ay_.get_data_output(); + cycle.set_value8_high(ay_.get_data_output()); ay_.set_control_lines(GI::AY38910::ControlLines(0)); } else { if(address == 0x7fc400) { ay_.set_control_lines(GI::AY38910::BC1); - ay_.set_data_input(cycle.value->halves.low); - ay_.set_control_lines(GI::AY38910::ControlLines(0)); } else { ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BDIR)); - ay_.set_data_input(cycle.value->halves.low); - ay_.set_control_lines(GI::AY38910::ControlLines(0)); } + ay_.set_data_input(cycle.value8_high()); + ay_.set_control_lines(GI::AY38910::ControlLines(0)); } /* @@ -441,28 +439,10 @@ class ConcreteMachine: case 0x7ffd1c: case 0x7ffd1d: case 0x7ffd1e: case 0x7ffd1f: if(!cycle.data_select_active()) return HalfCycles(0); - // The lower data lines aren't connected. - if(!cycle.upper_data_select()) { - if(cycle.operation & Microcycle::Read) { - cycle.value->halves.low = 0xff; - } - return HalfCycles(0); - } - if(cycle.operation & Microcycle::Read) { - const uint8_t value = mfp_->read(int(address)); - if(cycle.operation & Microcycle::SelectByte) { - cycle.value->halves.low = value; - } else { - cycle.value->halves.high = value; - cycle.value->halves.low = 0xff; - } + cycle.set_value8_low(mfp_->read(int(address))); } else { - if(cycle.operation & Microcycle::SelectByte) { - mfp_->write(int(address), cycle.value->halves.low); - } else { - mfp_->write(int(address), cycle.value->halves.high); - } + mfp_->write(int(address), cycle.value8_low()); } break; @@ -483,19 +463,9 @@ class ConcreteMachine: if(!cycle.data_select_active()) return HalfCycles(0); if(cycle.operation & Microcycle::Read) { - const uint8_t value = video_->read(int(address)); - if(cycle.operation & Microcycle::SelectByte) { - cycle.value->halves.low = value; - } else { - cycle.value->halves.high = value; - cycle.value->halves.low = 0xff; - } + cycle.set_value16(video_->read(int(address))); } else { - if(cycle.operation & Microcycle::SelectByte) { - video_->write(int(address), uint16_t(cycle.value->halves.low << cycle.byte_shift())); - } else { - video_->write(int(address), cycle.value->full); - } + video_->write(int(address), cycle.value16()); } break; @@ -506,21 +476,10 @@ class ConcreteMachine: if(!cycle.data_select_active()) return HalfCycles(0); const auto acia_ = (address < 0x7ffe02) ? &keyboard_acia_ : &midi_acia_; - if(cycle.operation & Microcycle::Read) { - const uint8_t value = (*acia_)->read(int(address)); - if(cycle.operation & Microcycle::SelectByte) { - cycle.value->halves.low = value; - } else { - cycle.value->halves.high = value; - cycle.value->halves.low = 0xff; - } + cycle.set_value8_high((*acia_)->read(int(address))); } else { - if(cycle.operation & Microcycle::SelectByte) { - (*acia_)->write(int(address), cycle.value->halves.low); - } else { - (*acia_)->write(int(address), cycle.value->halves.high); - } + (*acia_)->write(int(address), cycle.value8_high()); } } break; @@ -529,21 +488,9 @@ class ConcreteMachine: if(!cycle.data_select_active()) return HalfCycles(0); if(cycle.operation & Microcycle::Read) { - const auto value = dma_->read(int(address)); - if(cycle.operation & Microcycle::SelectWord) { - cycle.value->full = value; - } else { - cycle.value->halves.low = uint8_t(value >> cycle.byte_shift()); - } + cycle.set_value16(dma_->read(int(address))); } else { - if(cycle.operation & Microcycle::SelectWord) { - dma_->write(int(address), cycle.value->full); - } else { - dma_->write(int(address), uint16_t( - (cycle.value->halves.low << cycle.byte_shift()) | - (0xff00 >> cycle.byte_shift()) - )); - } + dma_->write(int(address), cycle.value16()); } break; } diff --git a/Machines/AtariST/Video.cpp b/Machines/AtariST/Video.cpp index 552d85039..b93ad648a 100644 --- a/Machines/AtariST/Video.cpp +++ b/Machines/AtariST/Video.cpp @@ -222,18 +222,18 @@ HalfCycles Video::get_next_sequence_point() { // MARK: - IO dispatch -uint8_t Video::read(int address) { +uint16_t Video::read(int address) { LOG("[Video] read " << PADHEX(2) << (address & 0x3f)); address &= 0x3f; switch(address) { default: break; - case 0x00: return uint8_t(base_address_ >> 16); - case 0x01: return uint8_t(base_address_ >> 8); - case 0x02: return uint8_t(current_address_ >> 16); - case 0x03: return uint8_t(current_address_ >> 8); - case 0x04: return uint8_t(current_address_); - case 0x30: return video_mode_ | 0xfc; + case 0x00: return uint16_t(0xff00 | (base_address_ >> 16)); + case 0x01: return uint16_t(0xff00 | (base_address_ >> 8)); + case 0x02: return uint16_t(0xff00 | (current_address_ >> 16)); + case 0x03: return uint16_t(0xff00 | (current_address_ >> 8)); + case 0x04: return uint16_t(0xff00 | (current_address_)); + case 0x30: return video_mode_ | 0xfcff; } return 0xff; } @@ -245,11 +245,11 @@ void Video::write(int address, uint16_t value) { default: break; // Start address. - case 0x00: base_address_ = (base_address_ & 0x00ffff) | (value << 16); break; - case 0x01: base_address_ = (base_address_ & 0xff00ff) | (value << 8); break; + case 0x00: base_address_ = (base_address_ & 0x00ffff) | ((value & 0xff) << 16); break; + case 0x01: base_address_ = (base_address_ & 0xff00ff) | ((value & 0xff) << 8); break; // Mode. - case 0x30: video_mode_ = uint8_t(value); break; + case 0x30: video_mode_ = value; break; // Palette. case 0x20: case 0x21: case 0x22: case 0x23: diff --git a/Machines/AtariST/Video.hpp b/Machines/AtariST/Video.hpp index e934afcd0..94be7b55b 100644 --- a/Machines/AtariST/Video.hpp +++ b/Machines/AtariST/Video.hpp @@ -41,7 +41,7 @@ class Video { void set_ram(uint16_t *); - uint8_t read(int address); + uint16_t read(int address); void write(int address, uint16_t value); private: @@ -58,7 +58,7 @@ class Video { int x = 0, y = 0; void output_border(int duration); - uint8_t video_mode_ = 0; + uint16_t video_mode_ = 0; }; } diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp index e1babcab6..4d484f0b6 100644 --- a/Processors/68000/68000.hpp +++ b/Processors/68000/68000.hpp @@ -193,6 +193,75 @@ struct Microcycle { return (address ? (*address) & 0x00fffffe : 0) >> 1; } + /*! + @returns the value on the data bus — all 16 bits, with any inactive lines + (as er the upper and lower data selects) being represented by 1s. Assumes + this is a write cycle. + */ + forceinline uint16_t value16() const { + if(operation & SelectWord) return value->full; + const auto shift = byte_shift(); + return uint16_t((value->halves.low << shift) | (0xff00 >> shift)); + } + + /*! + @returns the value currently on the high 8 lines of the data bus if any; + @c 0xff otherwise. Assumes this is a write cycle. + */ + forceinline uint8_t value8_high() const { + if(operation & SelectWord) { + return uint8_t(value->full >> 8); + } + + return uint8_t(value->halves.low | (0xff00 >> ((*address & 1) << 3))); + } + + /*! + @returns the value currently on the low 8 lines of the data bus if any; + @c 0xff otherwise. Assumes this is a write cycle. + */ + forceinline uint8_t value8_low() const { + if(operation & SelectWord) { + return uint8_t(value->full); + } + + return uint8_t(value->halves.low | (0x00ff << ((*address & 1) << 3))); + } + + /*! + Sets to @c value the 8- or 16-bit portion of the supplied value that is + currently being read. Assumes this is a read cycle. + */ + forceinline void set_value16(uint16_t v) const { + if(operation & Microcycle::SelectWord) { + value->full = v; + } else { + value->halves.low = uint8_t(v >> byte_shift()); + } + } + + /*! + Equivalent to set_value16((v << 8) | 0x00ff). + */ + forceinline void set_value8_high(uint8_t v) const { + if(operation & Microcycle::SelectWord) { + value->full = uint16_t(0x00ff | (v << 8)); + } else { + value->halves.low = uint8_t(v | (0xff00 >> ((*address & 1) << 3))); + } + } + + /*! + Equivalent to set_value16((v) | 0xff00). + */ + forceinline void set_value8_low(uint8_t v) const { + if(operation & Microcycle::SelectWord) { + value->full = 0xff00 | v; + } else { + value->halves.low = uint8_t(v | (0x00ff << ((*address & 1) << 3))); + } + } + /*! @returns the same value as word_address() for any Microcycle with the NewAddress or SameAddress flags set; undefined behaviour otherwise. diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 14b1d2fde..b9cb9a01e 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -70,7 +70,7 @@ template void Proces const HalfCycles remaining_duration = duration + half_cycles_left_to_run_; #ifdef LOG_TRACE - static bool should_log = true; + static bool should_log = false; #endif // This loop counts upwards rather than downwards because it simplifies calculation of @@ -241,6 +241,9 @@ template void Proces continue; case ExecutionState::BeginInterrupt: +#ifdef LOG_TRACE + should_log = true; +#endif active_program_ = nullptr; active_micro_op_ = interrupt_micro_ops_; execution_state_ = ExecutionState::Executing; @@ -1997,6 +2000,8 @@ template void Proces // Otherwise, the vector is whatever we were just told it is. effective_address_[0].full = uint32_t(source_bus_data_[0].halves.low.halves.low << 2); + + printf("Interrupt vector: %06x\n", effective_address_[0].full); break; case int_type(MicroOp::Action::CopyNextWord):