1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-24 12:30:17 +00:00

Attempts to regularise data bus access.

This commit is contained in:
Thomas Harte 2019-11-01 23:01:06 -04:00
parent 75e34b4215
commit c070f2100c
5 changed files with 99 additions and 78 deletions

View File

@ -398,23 +398,21 @@ class ConcreteMachine:
case 0x7fc401: /* PSG: write to write register. */ case 0x7fc401: /* PSG: write to write register. */
if(!cycle.data_select_active()) return HalfCycles(0); if(!cycle.data_select_active()) return HalfCycles(0);
// TODO: byte accesses to the odd addresses shouldn't obey logic below.
advance_time(HalfCycles(2)); advance_time(HalfCycles(2));
update_audio(); update_audio();
if(cycle.operation & Microcycle::Read) { if(cycle.operation & Microcycle::Read) {
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BC1)); 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)); ay_.set_control_lines(GI::AY38910::ControlLines(0));
} else { } else {
if(address == 0x7fc400) { if(address == 0x7fc400) {
ay_.set_control_lines(GI::AY38910::BC1); ay_.set_control_lines(GI::AY38910::BC1);
ay_.set_data_input(cycle.value->halves.low);
ay_.set_control_lines(GI::AY38910::ControlLines(0));
} else { } else {
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BDIR)); 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: case 0x7ffd1c: case 0x7ffd1d: case 0x7ffd1e: case 0x7ffd1f:
if(!cycle.data_select_active()) return HalfCycles(0); 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) { if(cycle.operation & Microcycle::Read) {
const uint8_t value = mfp_->read(int(address)); cycle.set_value8_low(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;
}
} else { } else {
if(cycle.operation & Microcycle::SelectByte) { mfp_->write(int(address), cycle.value8_low());
mfp_->write(int(address), cycle.value->halves.low);
} else {
mfp_->write(int(address), cycle.value->halves.high);
}
} }
break; break;
@ -483,19 +463,9 @@ class ConcreteMachine:
if(!cycle.data_select_active()) return HalfCycles(0); if(!cycle.data_select_active()) return HalfCycles(0);
if(cycle.operation & Microcycle::Read) { if(cycle.operation & Microcycle::Read) {
const uint8_t value = video_->read(int(address)); cycle.set_value16(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;
}
} else { } else {
if(cycle.operation & Microcycle::SelectByte) { video_->write(int(address), cycle.value16());
video_->write(int(address), uint16_t(cycle.value->halves.low << cycle.byte_shift()));
} else {
video_->write(int(address), cycle.value->full);
}
} }
break; break;
@ -506,21 +476,10 @@ class ConcreteMachine:
if(!cycle.data_select_active()) return HalfCycles(0); if(!cycle.data_select_active()) return HalfCycles(0);
const auto acia_ = (address < 0x7ffe02) ? &keyboard_acia_ : &midi_acia_; const auto acia_ = (address < 0x7ffe02) ? &keyboard_acia_ : &midi_acia_;
if(cycle.operation & Microcycle::Read) { if(cycle.operation & Microcycle::Read) {
const uint8_t value = (*acia_)->read(int(address)); cycle.set_value8_high((*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;
}
} else { } else {
if(cycle.operation & Microcycle::SelectByte) { (*acia_)->write(int(address), cycle.value8_high());
(*acia_)->write(int(address), cycle.value->halves.low);
} else {
(*acia_)->write(int(address), cycle.value->halves.high);
}
} }
} break; } break;
@ -529,21 +488,9 @@ class ConcreteMachine:
if(!cycle.data_select_active()) return HalfCycles(0); if(!cycle.data_select_active()) return HalfCycles(0);
if(cycle.operation & Microcycle::Read) { if(cycle.operation & Microcycle::Read) {
const auto value = dma_->read(int(address)); cycle.set_value16(dma_->read(int(address)));
if(cycle.operation & Microcycle::SelectWord) {
cycle.value->full = value;
} else {
cycle.value->halves.low = uint8_t(value >> cycle.byte_shift());
}
} else { } else {
if(cycle.operation & Microcycle::SelectWord) { dma_->write(int(address), cycle.value16());
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())
));
}
} }
break; break;
} }

View File

@ -222,18 +222,18 @@ HalfCycles Video::get_next_sequence_point() {
// MARK: - IO dispatch // MARK: - IO dispatch
uint8_t Video::read(int address) { uint16_t Video::read(int address) {
LOG("[Video] read " << PADHEX(2) << (address & 0x3f)); LOG("[Video] read " << PADHEX(2) << (address & 0x3f));
address &= 0x3f; address &= 0x3f;
switch(address) { switch(address) {
default: default:
break; break;
case 0x00: return uint8_t(base_address_ >> 16); case 0x00: return uint16_t(0xff00 | (base_address_ >> 16));
case 0x01: return uint8_t(base_address_ >> 8); case 0x01: return uint16_t(0xff00 | (base_address_ >> 8));
case 0x02: return uint8_t(current_address_ >> 16); case 0x02: return uint16_t(0xff00 | (current_address_ >> 16));
case 0x03: return uint8_t(current_address_ >> 8); case 0x03: return uint16_t(0xff00 | (current_address_ >> 8));
case 0x04: return uint8_t(current_address_); case 0x04: return uint16_t(0xff00 | (current_address_));
case 0x30: return video_mode_ | 0xfc; case 0x30: return video_mode_ | 0xfcff;
} }
return 0xff; return 0xff;
} }
@ -245,11 +245,11 @@ void Video::write(int address, uint16_t value) {
default: break; default: break;
// Start address. // Start address.
case 0x00: base_address_ = (base_address_ & 0x00ffff) | (value << 16); break; case 0x00: base_address_ = (base_address_ & 0x00ffff) | ((value & 0xff) << 16); break;
case 0x01: base_address_ = (base_address_ & 0xff00ff) | (value << 8); break; case 0x01: base_address_ = (base_address_ & 0xff00ff) | ((value & 0xff) << 8); break;
// Mode. // Mode.
case 0x30: video_mode_ = uint8_t(value); break; case 0x30: video_mode_ = value; break;
// Palette. // Palette.
case 0x20: case 0x21: case 0x22: case 0x23: case 0x20: case 0x21: case 0x22: case 0x23:

View File

@ -41,7 +41,7 @@ class Video {
void set_ram(uint16_t *); void set_ram(uint16_t *);
uint8_t read(int address); uint16_t read(int address);
void write(int address, uint16_t value); void write(int address, uint16_t value);
private: private:
@ -58,7 +58,7 @@ class Video {
int x = 0, y = 0; int x = 0, y = 0;
void output_border(int duration); void output_border(int duration);
uint8_t video_mode_ = 0; uint16_t video_mode_ = 0;
}; };
} }

View File

@ -193,6 +193,75 @@ struct Microcycle {
return (address ? (*address) & 0x00fffffe : 0) >> 1; 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 @returns the same value as word_address() for any Microcycle with the NewAddress or
SameAddress flags set; undefined behaviour otherwise. SameAddress flags set; undefined behaviour otherwise.

View File

@ -70,7 +70,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
const HalfCycles remaining_duration = duration + half_cycles_left_to_run_; const HalfCycles remaining_duration = duration + half_cycles_left_to_run_;
#ifdef LOG_TRACE #ifdef LOG_TRACE
static bool should_log = true; static bool should_log = false;
#endif #endif
// This loop counts upwards rather than downwards because it simplifies calculation of // This loop counts upwards rather than downwards because it simplifies calculation of
@ -241,6 +241,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
continue; continue;
case ExecutionState::BeginInterrupt: case ExecutionState::BeginInterrupt:
#ifdef LOG_TRACE
should_log = true;
#endif
active_program_ = nullptr; active_program_ = nullptr;
active_micro_op_ = interrupt_micro_ops_; active_micro_op_ = interrupt_micro_ops_;
execution_state_ = ExecutionState::Executing; execution_state_ = ExecutionState::Executing;
@ -1997,6 +2000,8 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
// Otherwise, the vector is whatever we were just told it is. // 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); 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; break;
case int_type(MicroOp::Action::CopyNextWord): case int_type(MicroOp::Action::CopyNextWord):