1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Eliminate runtime switch.

This commit is contained in:
Thomas Harte 2023-11-27 14:57:41 -05:00
parent 5c7f94d2ef
commit 032eeb4757
4 changed files with 42 additions and 27 deletions

View File

@ -179,32 +179,38 @@ void MFP68901::write(int address, uint8_t value) {
update_clocking_observer(); update_clocking_observer();
} }
template <int timer>
void MFP68901::run_timer_for(int cycles) {
if(timers_[timer].mode >= TimerMode::Delay) {
// This code applies the timer prescaling only. prescale_count is used to count
// upwards rather than downwards for simplicity, but on the real hardware it's
// pretty safe to assume it actually counted downwards. So the clamp to 0 is
// because gymnastics may need to occur when the prescale value is altered, e.g.
// if a prescale of 256 is set and the prescale_count is currently 2 then the
// counter should roll over in 254 cycles. If the user at that point changes the
// prescale_count to 1 then the counter will need to be altered to -253 and
// allowed to keep counting up until it crosses both 0 and 1.
const int dividend = timers_[timer].prescale_count + cycles;
const int decrements = std::max(dividend / timers_[timer].prescale, 0);
if(decrements) {
decrement_timer<timer>(decrements);
timers_[timer].prescale_count = dividend % timers_[timer].prescale;
} else {
timers_[timer].prescale_count += cycles;
}
}
}
void MFP68901::run_for(HalfCycles time) { void MFP68901::run_for(HalfCycles time) {
cycles_left_ += time; cycles_left_ += time;
const int cycles = int(cycles_left_.flush<Cycles>().as_integral()); const int cycles = int(cycles_left_.flush<Cycles>().as_integral());
if(!cycles) return; if(!cycles) return;
for(int c = 0; c < 4; ++c) { run_timer_for<0>(cycles);
if(timers_[c].mode >= TimerMode::Delay) { run_timer_for<1>(cycles);
// This code applies the timer prescaling only. prescale_count is used to count run_timer_for<2>(cycles);
// upwards rather than downwards for simplicity, but on the real hardware it's run_timer_for<3>(cycles);
// pretty safe to assume it actually counted downwards. So the clamp to 0 is
// because gymnastics may need to occur when the prescale value is altered, e.g.
// if a prescale of 256 is set and the prescale_count is currently 2 then the
// counter should roll over in 254 cycles. If the user at that point changes the
// prescale_count to 1 then the counter will need to be altered to -253 and
// allowed to keep counting up until it crosses both 0 and 1.
const int dividend = timers_[c].prescale_count + cycles;
const int decrements = std::max(dividend / timers_[c].prescale, 0);
if(decrements) {
decrement_timer(c, decrements);
timers_[c].prescale_count = dividend % timers_[c].prescale;
} else {
timers_[c].prescale_count += cycles;
}
}
}
} }
HalfCycles MFP68901::next_sequence_point() { HalfCycles MFP68901::next_sequence_point() {
@ -240,7 +246,8 @@ uint8_t MFP68901::get_timer_data(int timer) {
return timers_[timer].value; return timers_[timer].value;
} }
void MFP68901::set_timer_event_input(int channel, bool value) { template <int channel>
void MFP68901::set_timer_event_input(bool value) {
if(timers_[channel].event_input == value) return; if(timers_[channel].event_input == value) return;
timers_[channel].event_input = value; timers_[channel].event_input = value;
@ -248,7 +255,7 @@ void MFP68901::set_timer_event_input(int channel, bool value) {
// "The active state of the signal on TAI or TBI is dependent upon the associated // "The active state of the signal on TAI or TBI is dependent upon the associated
// Interrupt Channels edge bit (GPIP 4 for TAI and GPIP 3 for TBI [...] ). // Interrupt Channels edge bit (GPIP 4 for TAI and GPIP 3 for TBI [...] ).
// If the edge bit associated with the TAI or TBI input is a one, it will be active high. // If the edge bit associated with the TAI or TBI input is a one, it will be active high.
decrement_timer(channel, 1); decrement_timer<channel>(1);
} }
// TODO: // TODO:
@ -261,7 +268,13 @@ void MFP68901::set_timer_event_input(int channel, bool value) {
// (the final bit probably explains 13 cycles of the DE to interrupt latency; not sure about the other ~15) // (the final bit probably explains 13 cycles of the DE to interrupt latency; not sure about the other ~15)
} }
void MFP68901::decrement_timer(int timer, int amount) { template void MFP68901::set_timer_event_input<0>(bool);
template void MFP68901::set_timer_event_input<1>(bool);
template void MFP68901::set_timer_event_input<2>(bool);
template void MFP68901::set_timer_event_input<3>(bool);
template <int timer>
void MFP68901::decrement_timer(int amount) {
while(amount--) { while(amount--) {
--timers_[timer].value; --timers_[timer].value;
if(timers_[timer].value < 1) { if(timers_[timer].value < 1) {

View File

@ -43,7 +43,8 @@ class MFP68901: public ClockingHint::Source {
HalfCycles next_sequence_point(); HalfCycles next_sequence_point();
/// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms. /// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms.
void set_timer_event_input(int channel, bool value); template <int channel>
void set_timer_event_input(bool value);
/// Sets a port handler, a receiver that will be notified upon any change in GPIP output. /// Sets a port handler, a receiver that will be notified upon any change in GPIP output.
/// ///
@ -86,7 +87,8 @@ class MFP68901: public ClockingHint::Source {
void set_timer_mode(int timer, TimerMode, int prescale, bool reset_timer); void set_timer_mode(int timer, TimerMode, int prescale, bool reset_timer);
void set_timer_data(int timer, uint8_t); void set_timer_data(int timer, uint8_t);
uint8_t get_timer_data(int timer); uint8_t get_timer_data(int timer);
void decrement_timer(int timer, int amount); template <int timer> void decrement_timer(int amount);
template <int timer> void run_timer_for(int cycles);
struct Timer { struct Timer {
TimerMode mode = TimerMode::Stopped; TimerMode mode = TimerMode::Stopped;

View File

@ -484,7 +484,7 @@ class ConcreteMachine:
length -= video_.cycles_until_implicit_flush(); length -= video_.cycles_until_implicit_flush();
video_ += video_.cycles_until_implicit_flush(); video_ += video_.cycles_until_implicit_flush();
mfp_->set_timer_event_input(1, video_->display_enabled()); mfp_->set_timer_event_input<1>(video_->display_enabled());
update_interrupt_input(); update_interrupt_input();
} }

View File

@ -62,7 +62,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"