1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +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. */
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;
}

View File

@ -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:

View File

@ -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;
};
}

View File

@ -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.

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_;
#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 <class T, bool dtack_is_implicit, bool signal_will_perform> 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 <class T, bool dtack_is_implicit, bool signal_will_perform> 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):