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:
parent
5c7f94d2ef
commit
032eeb4757
@ -179,32 +179,38 @@ void MFP68901::write(int address, uint8_t value) {
|
||||
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) {
|
||||
cycles_left_ += time;
|
||||
|
||||
const int cycles = int(cycles_left_.flush<Cycles>().as_integral());
|
||||
if(!cycles) return;
|
||||
|
||||
for(int c = 0; c < 4; ++c) {
|
||||
if(timers_[c].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_[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
run_timer_for<0>(cycles);
|
||||
run_timer_for<1>(cycles);
|
||||
run_timer_for<2>(cycles);
|
||||
run_timer_for<3>(cycles);
|
||||
}
|
||||
|
||||
HalfCycles MFP68901::next_sequence_point() {
|
||||
@ -240,7 +246,8 @@ uint8_t MFP68901::get_timer_data(int timer) {
|
||||
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;
|
||||
|
||||
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
|
||||
// Interrupt Channel’s 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.
|
||||
decrement_timer(channel, 1);
|
||||
decrement_timer<channel>(1);
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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--) {
|
||||
--timers_[timer].value;
|
||||
if(timers_[timer].value < 1) {
|
||||
|
@ -43,7 +43,8 @@ class MFP68901: public ClockingHint::Source {
|
||||
HalfCycles next_sequence_point();
|
||||
|
||||
/// 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.
|
||||
///
|
||||
@ -86,7 +87,8 @@ class MFP68901: public ClockingHint::Source {
|
||||
void set_timer_mode(int timer, TimerMode, int prescale, bool reset_timer);
|
||||
void set_timer_data(int timer, uint8_t);
|
||||
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 {
|
||||
TimerMode mode = TimerMode::Stopped;
|
||||
|
@ -484,7 +484,7 @@ class ConcreteMachine:
|
||||
length -= 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();
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
Loading…
Reference in New Issue
Block a user