mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-07 21:57:46 +00:00
Implement reset logic, advance as far as actually performing an NBCD on D0 (but not writing it back).
This commit is contained in:
parent
1a27eea46c
commit
84071ac6d0
@ -32,7 +32,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#define CheckOverrun() if constexpr (permit_overrun) ConsiderExit()
|
#define CheckOverrun() if constexpr (permit_overrun) ConsiderExit()
|
||||||
|
|
||||||
// Sets `x` as the next state, and exits now if all remaining time has been extended and permit_overrun is true.
|
// Sets `x` as the next state, and exits now if all remaining time has been extended and permit_overrun is true.
|
||||||
#define MoveToState(x) state_ = x; if (permit_overrun && time_remaining_ <= HalfCycles(0)) return
|
#define MoveToState(x) state_ = (x); if (permit_overrun && time_remaining_ <= HalfCycles(0)) return
|
||||||
|
|
||||||
//
|
//
|
||||||
// So basic structure is, in general:
|
// So basic structure is, in general:
|
||||||
@ -167,6 +167,12 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
case State::Reset:
|
case State::Reset:
|
||||||
IdleBus(7); // (n-)*5 nn
|
IdleBus(7); // (n-)*5 nn
|
||||||
|
|
||||||
|
// Establish general reset state.
|
||||||
|
status_.is_supervisor = true;
|
||||||
|
status_.interrupt_level = 7;
|
||||||
|
status_.trace_flag = 0;
|
||||||
|
did_update_status();
|
||||||
|
|
||||||
address = 0; ReadDataWord(address, registers_[15].high); // nF
|
address = 0; ReadDataWord(address, registers_[15].high); // nF
|
||||||
address += 2; ReadDataWord(address, registers_[15].low); // nf
|
address += 2; ReadDataWord(address, registers_[15].low); // nf
|
||||||
address += 2; ReadDataWord(address, program_counter_.high); // nV
|
address += 2; ReadDataWord(address, program_counter_.high); // nV
|
||||||
@ -195,7 +201,14 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
// Check the operand flags to determine whether the operand at index
|
// Check the operand flags to determine whether the operand at index
|
||||||
// operand_ needs to be fetched, and do so.
|
// operand_ needs to be fetched, and if so then calculate the EA and
|
||||||
|
// do so.
|
||||||
|
//
|
||||||
|
// Per Yacht, all instructions other than MOVE.[b/w/;] will read all
|
||||||
|
// relevant operands — even when that's a useless endeavour, such as
|
||||||
|
// for CLR or MOVE SR, <ea>.
|
||||||
|
//
|
||||||
|
// TODO: add MOVE special case, somewhere.
|
||||||
case State::FetchOperand:
|
case State::FetchOperand:
|
||||||
switch(instruction_.mode(next_operand_)) {
|
switch(instruction_.mode(next_operand_)) {
|
||||||
case Mode::None:
|
case Mode::None:
|
||||||
@ -206,16 +219,39 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
case Mode::DataRegisterDirect:
|
case Mode::DataRegisterDirect:
|
||||||
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
|
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
|
||||||
++next_operand_;
|
++next_operand_;
|
||||||
state_ = next_operand_ == 2 ? perform_state_ : state_;
|
state_ = next_operand_ == 2 ? perform_state_ : State::FetchOperand;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Various forms of perform.
|
||||||
|
//
|
||||||
|
case State::Perform_np:
|
||||||
|
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
|
||||||
|
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
|
||||||
|
Prefetch(); // np
|
||||||
|
|
||||||
|
next_operand_ = 0;
|
||||||
|
MoveToState(operand_flags_ & 0x0c ? State::StoreOperand : State::Decode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::Perform_np_n:
|
||||||
|
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
|
||||||
|
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
|
||||||
|
Prefetch(); // np
|
||||||
|
IdleBus(1); // n
|
||||||
|
|
||||||
|
next_operand_ = 0;
|
||||||
|
MoveToState(operand_flags_ & 0x0c ? State::StoreOperand : State::Decode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
[[fallthrough]];
|
|
||||||
default:
|
default:
|
||||||
printf("Unhandled or unterminated state: %d\n", state_);
|
printf("Unhandled state: %d\n", state_);
|
||||||
assert(false);
|
assert(false);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@ -240,11 +276,13 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#define BIND(x, p) \
|
#define BIND(x, p) \
|
||||||
case InstructionSet::M68k::Operation::x: \
|
case InstructionSet::M68k::Operation::x: \
|
||||||
operand_flags_ = InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>(); \
|
operand_flags_ = InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>(); \
|
||||||
perform_state_ = State::p; \
|
perform_state_ = p; \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
using Mode = InstructionSet::M68k::AddressingMode;
|
||||||
|
|
||||||
switch(instruction_.operation) {
|
switch(instruction_.operation) {
|
||||||
BIND(NBCD, Perform_np);
|
BIND(NBCD, instruction_.mode(0) == Mode::DataRegisterDirect ? State::Perform_np_n : State::Perform_np);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -253,6 +291,17 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#undef BIND
|
#undef BIND
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Flow Controller.
|
||||||
|
|
||||||
|
void ProcessorBase::did_update_status() {
|
||||||
|
// Shuffle the stack pointers.
|
||||||
|
stack_pointers_[is_supervisor_] = registers_[7];
|
||||||
|
registers_[7] = stack_pointers_[int(status_.is_supervisor)];
|
||||||
|
is_supervisor_ = int(status_.is_supervisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - External state.
|
||||||
|
|
||||||
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
|
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
|
||||||
CPU::MC68000Mk2::State Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::get_state() {
|
CPU::MC68000Mk2::State Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::get_state() {
|
||||||
return CPU::MC68000Mk2::State();
|
return CPU::MC68000Mk2::State();
|
||||||
@ -262,6 +311,7 @@ template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool si
|
|||||||
void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::set_state(const CPU::MC68000Mk2::State &) {
|
void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::set_state(const CPU::MC68000Mk2::State &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,13 +9,14 @@
|
|||||||
#ifndef _8000Mk2Storage_h
|
#ifndef _8000Mk2Storage_h
|
||||||
#define _8000Mk2Storage_h
|
#define _8000Mk2Storage_h
|
||||||
|
|
||||||
#include "../../../InstructionSets/M68k/Status.hpp"
|
|
||||||
#include "../../../InstructionSets/M68k/Decoder.hpp"
|
#include "../../../InstructionSets/M68k/Decoder.hpp"
|
||||||
|
#include "../../../InstructionSets/M68k/Perform.hpp"
|
||||||
|
#include "../../../InstructionSets/M68k/Status.hpp"
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
namespace MC68000Mk2 {
|
namespace MC68000Mk2 {
|
||||||
|
|
||||||
struct ProcessorBase {
|
struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
||||||
/// States for the state machine which are named by
|
/// States for the state machine which are named by
|
||||||
/// me for their purpose rather than automatically by file position.
|
/// me for their purpose rather than automatically by file position.
|
||||||
/// These are negative to avoid ambiguity with the other group.
|
/// These are negative to avoid ambiguity with the other group.
|
||||||
@ -24,6 +25,7 @@ struct ProcessorBase {
|
|||||||
Decode = -2,
|
Decode = -2,
|
||||||
WaitForDTACK = -3,
|
WaitForDTACK = -3,
|
||||||
FetchOperand = -4,
|
FetchOperand = -4,
|
||||||
|
StoreOperand = -5,
|
||||||
|
|
||||||
// Various different effective address calculations.
|
// Various different effective address calculations.
|
||||||
|
|
||||||
@ -34,6 +36,7 @@ struct ProcessorBase {
|
|||||||
// indicated bus cycle.
|
// indicated bus cycle.
|
||||||
|
|
||||||
Perform_np = -6,
|
Perform_np = -6,
|
||||||
|
Perform_np_n = -7,
|
||||||
};
|
};
|
||||||
int state_ = State::Reset;
|
int state_ = State::Reset;
|
||||||
|
|
||||||
@ -86,6 +89,38 @@ struct ProcessorBase {
|
|||||||
/// When fetching or storing operands, this is the next one to fetch
|
/// When fetching or storing operands, this is the next one to fetch
|
||||||
/// or store.
|
/// or store.
|
||||||
int next_operand_ = 0;
|
int next_operand_ = 0;
|
||||||
|
|
||||||
|
// Flow controller... all TODO.
|
||||||
|
using Preinstruction = InstructionSet::M68k::Preinstruction;
|
||||||
|
|
||||||
|
template <typename IntT> void did_mulu(IntT) {}
|
||||||
|
template <typename IntT> void did_muls(IntT) {}
|
||||||
|
void did_chk([[maybe_unused]] bool was_under, [[maybe_unused]] bool was_over) {}
|
||||||
|
void did_shift([[maybe_unused]] int bit_count) {}
|
||||||
|
template <bool did_overflow> void did_divu([[maybe_unused]] uint32_t dividend, [[maybe_unused]] uint32_t divisor) {}
|
||||||
|
template <bool did_overflow> void did_divs([[maybe_unused]] int32_t dividend, [[maybe_unused]] int32_t divisor) {}
|
||||||
|
void did_bit_op([[maybe_unused]] int bit_position) {}
|
||||||
|
inline void did_update_status();
|
||||||
|
template <typename IntT> void complete_bcc(bool matched_condition, IntT offset) {}
|
||||||
|
void complete_dbcc(bool matched_condition, bool overflowed, int16_t offset) {}
|
||||||
|
void bsr(uint32_t offset) {}
|
||||||
|
void jsr(uint32_t address) {}
|
||||||
|
void jmp(uint32_t address) {}
|
||||||
|
void rtr() {}
|
||||||
|
void rte() {}
|
||||||
|
void rts() {}
|
||||||
|
void stop() {}
|
||||||
|
void reset() {}
|
||||||
|
void link(Preinstruction instruction, uint32_t offset) {}
|
||||||
|
void unlink(uint32_t &address) {}
|
||||||
|
void pea(uint32_t address) {}
|
||||||
|
void move_to_usp(uint32_t address) {}
|
||||||
|
void move_from_usp(uint32_t &address) {}
|
||||||
|
void tas(Preinstruction instruction, uint32_t address) {}
|
||||||
|
template <typename IntT> void movep(Preinstruction instruction, uint32_t source, uint32_t dest) {}
|
||||||
|
template <typename IntT> void movem_toM(Preinstruction instruction, uint32_t mask, uint32_t address) {}
|
||||||
|
template <typename IntT> void movem_toR(Preinstruction instruction, uint32_t mask, uint32_t address) {}
|
||||||
|
template <bool use_current_instruction_pc = true> void raise_exception([[maybe_unused]] int vector) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user