1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-16 18:30:32 +00:00

Breaks up loop for arithmetic simplicity.

This commit is contained in:
Thomas Harte 2021-07-27 21:59:27 -04:00
parent 402eab10f8
commit 82205d71cc
2 changed files with 48 additions and 44 deletions

View File

@ -127,6 +127,8 @@ bool Chipset::Copper::advance(uint16_t position) {
} }
template <int cycle> void Chipset::output() { template <int cycle> void Chipset::output() {
// Notes to self on guesses below:
//
// Hardware stop is at 0x18; // Hardware stop is at 0x18;
// 12/64 * 227 = 42.5625 // 12/64 * 227 = 42.5625
// //
@ -242,6 +244,41 @@ template <int cycle, bool stop_if_cpu> bool Chipset::perform_cycle() {
return false; return false;
} }
template <bool stop_on_cpu> int Chipset::advance_slots(int first_slot, int last_slot) {
if(first_slot == last_slot) {
return -1;
}
#define C(x) \
case x: \
if constexpr(stop_on_cpu) {\
if(perform_cycle<x, stop_on_cpu>()) {\
return x - first_slot;\
}\
} else {\
perform_cycle<x, stop_on_cpu>(); \
} \
output<x>(); \
if((x + 1) == last_slot) break; \
[[fallthrough]]
#define C10(x) C(x); C(x+1); C(x+2); C(x+3); C(x+4); C(x+5); C(x+6); C(x+7); C(x+8); C(x+9);
switch(first_slot) {
C10(0); C10(10); C10(20); C10(30); C10(40);
C10(50); C10(60); C10(70); C10(80); C10(90);
C10(100); C10(110); C10(120); C10(130); C10(140);
C10(150); C10(160); C10(170); C10(180); C10(190);
C10(200); C10(210);
C(220); C(221); C(222); C(223); C(224);
C(225); C(226); C(227); C(228);
default: assert(false);
}
#undef C
return -1;
}
template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) { template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
Changes changes; Changes changes;
@ -252,54 +289,19 @@ template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
// Update raster position, spooling out graphics. // Update raster position, spooling out graphics.
while(pixels_remaining) { while(pixels_remaining) {
// Determine number of pixels left on this line. // Determine number of pixels left on this line.
int line_pixels = std::min(pixels_remaining, (line_length_ * 4) - line_cycle_); const int line_pixels = std::min(pixels_remaining, (line_length_ * 4) - line_cycle_);
// const int start_slot = line_cycle_ >> 2;
// Run DMA scheduler. const int end_slot = (line_cycle_ + line_pixels) >> 2;
// const int actual_slots = advance_slots<stop_on_cpu>(start_slot, end_slot);
int final_slot = (line_cycle_ + line_pixels) >> 2; if(actual_slots >= 0) {
// TODO: abbreviate run, prior to adding to totals below.
if((line_cycle_ >> 2) == final_slot) { assert(false);
// Not enough pixels left to fill any whole slots, just stop.
line_cycle_ += line_pixels;
break;
} }
// Advance to window boundary. line_cycle_ += line_pixels;
const int distance_to_boundary = ((line_cycle_ - 1) & 3) ^ 3; pixels_remaining -= line_pixels;
line_pixels -= distance_to_boundary;
pixels_remaining -= distance_to_boundary;
line_cycle_ += distance_to_boundary;
#define C(x) \
case x: \
assert(!(line_cycle_&3)); \
if constexpr(stop_on_cpu) {\
if(perform_cycle<x, stop_on_cpu>()) {\
break;\
}\
} else {\
perform_cycle<x, stop_on_cpu>(); \
} \
output<x>(); \
if((line_cycle_ >> 2) == final_slot) break; \
line_cycle_ += 4; \
pixels_remaining -= 4;
#define C10(x) C(x); C(x+1); C(x+2); C(x+3); C(x+4); C(x+5); C(x+6); C(x+7); C(x+8); C(x+9);
switch(line_cycle_ >> 2) {
C10(0); C10(10); C10(20); C10(30); C10(40);
C10(50); C10(60); C10(70); C10(80); C10(90);
C10(100); C10(110); C10(120); C10(130); C10(140);
C10(150); C10(160); C10(170); C10(180); C10(190);
C10(200); C10(210);
C(220); C(221); C(222); C(223); C(224);
C(225); C(226); C(227); C(228);
default: assert(false);
}
#undef C
// Advance intraline counter and possibly ripple upwards into // Advance intraline counter and possibly ripple upwards into
// lines and fields. // lines and fields.
@ -320,6 +322,7 @@ template <bool stop_on_cpu> Chipset::Changes Chipset::run(HalfCycles length) {
copper_.reload(0); copper_.reload(0);
} }
} }
assert(line_cycle_ < line_length_ * 4);
} }
changes.interrupt_level = interrupt_level_; changes.interrupt_level = interrupt_level_;

View File

@ -66,6 +66,7 @@ class Chipset {
// MARK: - Scheduler. // MARK: - Scheduler.
template <bool stop_on_cpu> Changes run(HalfCycles duration = HalfCycles()); template <bool stop_on_cpu> Changes run(HalfCycles duration = HalfCycles());
template <bool stop_on_cpu> int advance_slots(int, int);
template <int cycle, bool stop_if_cpu> bool perform_cycle(); template <int cycle, bool stop_if_cpu> bool perform_cycle();
template <int cycle> void output(); template <int cycle> void output();