mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-19 14:25:35 +00:00
Flattens the Macintosh's perform_bus_operation, for legibility.
This commit is contained in:
parent
69b94719a1
commit
7886cd63bd
@ -137,6 +137,9 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
using Microcycle = CPU::MC68000::Microcycle;
|
using Microcycle = CPU::MC68000::Microcycle;
|
||||||
|
|
||||||
HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
|
HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
|
||||||
|
// TODO: pick a delay if this is a video-clashing memory fetch.
|
||||||
|
HalfCycles delay(0);
|
||||||
|
|
||||||
time_since_video_update_ += cycle.length;
|
time_since_video_update_ += cycle.length;
|
||||||
iwm_.time_since_update += cycle.length;
|
iwm_.time_since_update += cycle.length;
|
||||||
|
|
||||||
@ -209,21 +212,23 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
} else {
|
} else {
|
||||||
mc68000_.set_interrupt_level(0);
|
mc68000_.set_interrupt_level(0);
|
||||||
}
|
}
|
||||||
// mc68000_.set_interrupt_level(
|
|
||||||
// (via_.get_interrupt_line() ? 1 : 0) |
|
|
||||||
// (scc_.get_interrupt_line() ? 2 : 0)
|
|
||||||
// /* TODO: to emulate a programmer's switch: have it set bit 2 when pressed. */
|
|
||||||
// );
|
|
||||||
|
|
||||||
// A null cycle leaves nothing else to do.
|
// A null cycle leaves nothing else to do.
|
||||||
if(cycle.operation) {
|
if(!cycle.operation) return delay;
|
||||||
|
|
||||||
auto word_address = cycle.word_address();
|
auto word_address = cycle.word_address();
|
||||||
|
|
||||||
// Everything above E0 0000 is signalled as being on the peripheral bus.
|
// Everything above E0 0000 is signalled as being on the peripheral bus.
|
||||||
mc68000_.set_is_peripheral_address(word_address >= 0x700000);
|
mc68000_.set_is_peripheral_address(word_address >= 0x700000);
|
||||||
|
|
||||||
|
// All code below deals only with reads and writes — cycles in which a
|
||||||
|
// data select is active. So quit now if this is not the active part of
|
||||||
|
// a read or write.
|
||||||
|
if(!cycle.data_select_active()) return delay;
|
||||||
|
|
||||||
|
// Check whether this access maps into the IO area; if so then
|
||||||
|
// apply more complicated decoding logic.
|
||||||
if(word_address >= 0x400000) {
|
if(word_address >= 0x400000) {
|
||||||
if(cycle.data_select_active()) {
|
|
||||||
const int register_address = word_address >> 8;
|
const int register_address = word_address >> 8;
|
||||||
|
|
||||||
switch(word_address & 0x78f000) {
|
switch(word_address & 0x78f000) {
|
||||||
@ -239,9 +244,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
|
|
||||||
case 0x68f000:
|
case 0x68f000:
|
||||||
// The IWM; this is a purely polled device, so can be run on demand.
|
// The IWM; this is a purely polled device, so can be run on demand.
|
||||||
#ifndef NDEBUG
|
|
||||||
// printf("[%06x]: ", mc68000_.get_state().program_counter);
|
|
||||||
#endif
|
|
||||||
iwm_.flush();
|
iwm_.flush();
|
||||||
if(cycle.operation & Microcycle::Read) {
|
if(cycle.operation & Microcycle::Read) {
|
||||||
cycle.value->halves.low = iwm_.iwm.read(register_address);
|
cycle.value->halves.low = iwm_.iwm.read(register_address);
|
||||||
@ -295,19 +297,20 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
|
if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff;
|
||||||
|
|
||||||
|
return delay;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if(cycle.data_select_active()) {
|
// Having reached here, this is a RAM or ROM access.
|
||||||
uint16_t *memory_base = nullptr;
|
|
||||||
auto operation = cycle.operation;
|
|
||||||
|
|
||||||
// When ROM overlay is enabled, the ROM begins at both $000000 and $400000,
|
// When ROM overlay is enabled, the ROM begins at both $000000 and $400000,
|
||||||
// and RAM is available at $600000.
|
// and RAM is available at $600000.
|
||||||
//
|
//
|
||||||
// Otherwise RAM is mapped at $000000 and ROM from $400000.
|
// Otherwise RAM is mapped at $000000 and ROM from $400000.
|
||||||
|
uint16_t *memory_base;
|
||||||
if(
|
if(
|
||||||
(ROM_is_overlay_ && word_address >= 0x300000) ||
|
(!ROM_is_overlay_ && word_address < 0x200000) ||
|
||||||
(!ROM_is_overlay_ && word_address < 0x200000)
|
(ROM_is_overlay_ && word_address >= 0x300000)
|
||||||
) {
|
) {
|
||||||
memory_base = ram_;
|
memory_base = ram_;
|
||||||
word_address &= ram_mask_;
|
word_address &= ram_mask_;
|
||||||
@ -316,12 +319,19 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
memory_base = rom_;
|
memory_base = rom_;
|
||||||
word_address &= rom_mask_;
|
word_address &= rom_mask_;
|
||||||
|
|
||||||
// Disallow writes to ROM; also it doesn't mirror above 0x60000, ever.
|
// Writes to ROM have no effect, and it doesn't mirror above 0x60000.
|
||||||
if(!(operation & Microcycle::Read) || word_address >= 0x300000) operation = 0;
|
if(!(cycle.operation & Microcycle::Read)) return delay;
|
||||||
|
if(word_address >= 0x300000) {
|
||||||
|
if(cycle.operation & Microcycle::SelectWord) {
|
||||||
|
cycle.value->full = 0xffff;
|
||||||
|
} else {
|
||||||
|
cycle.value->halves.low = 0xff;
|
||||||
|
}
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto masked_operation = operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read | Microcycle::InterruptAcknowledge);
|
switch(cycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read | Microcycle::InterruptAcknowledge)) {
|
||||||
switch(masked_operation) {
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -350,28 +360,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(!(operation & Microcycle::Read) && (word_address == (0x00000172 >> 1))) {
|
|
||||||
// if(operation & Microcycle::SelectByte)
|
|
||||||
// printf("MBState: %02x\n", cycle.value->halves.low);
|
|
||||||
// else
|
|
||||||
// printf("MBState: %04x\n", cycle.value->full);
|
|
||||||
// }
|
|
||||||
// if(
|
|
||||||
// (
|
|
||||||
// (word_address == (0x00000352 >> 1))
|
|
||||||
// || (word_address == (0x00000354 >> 1))
|
|
||||||
// || (word_address == (0x00005d16 >> 1))
|
|
||||||
// )
|
|
||||||
// ) {
|
|
||||||
// printf("%s %08x: %04x from around %08x\n", (operation & Microcycle::Read) ? "Read" : "Write", word_address << 1, memory_base[word_address], mc68000_.get_state().program_counter);
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
// TODO: add delay if this is a RAM access and video blocks it momentarily.
|
|
||||||
// "Each [video] fetch took two cycles out of eight"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Normal memory map:
|
Normal memory map:
|
||||||
|
|
||||||
@ -383,7 +371,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
EFE1FE+: VIA
|
EFE1FE+: VIA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return HalfCycles(0);
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush() {
|
void flush() {
|
||||||
|
Loading…
Reference in New Issue
Block a user