2022-05-16 15:44:16 +00:00
|
|
|
|
//
|
|
|
|
|
// 68000Mk2Storage.hpp
|
|
|
|
|
// Clock Signal
|
|
|
|
|
//
|
|
|
|
|
// Created by Thomas Harte on 16/05/2022.
|
|
|
|
|
// Copyright © 2022 Thomas Harte. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#ifndef _8000Mk2Storage_h
|
|
|
|
|
#define _8000Mk2Storage_h
|
|
|
|
|
|
2022-05-16 20:57:40 +00:00
|
|
|
|
#include "../../../InstructionSets/M68k/Decoder.hpp"
|
2022-05-17 18:51:49 +00:00
|
|
|
|
#include "../../../InstructionSets/M68k/Perform.hpp"
|
|
|
|
|
#include "../../../InstructionSets/M68k/Status.hpp"
|
2022-05-16 20:57:40 +00:00
|
|
|
|
|
2022-05-18 19:35:38 +00:00
|
|
|
|
#include <limits>
|
|
|
|
|
|
2022-05-16 15:44:16 +00:00
|
|
|
|
namespace CPU {
|
|
|
|
|
namespace MC68000Mk2 {
|
|
|
|
|
|
2022-05-17 18:51:49 +00:00
|
|
|
|
struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
2022-05-19 14:27:51 +00:00
|
|
|
|
ProcessorBase() {
|
|
|
|
|
read_program_announce.address = read_program.address = &program_counter_.l;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-18 19:35:38 +00:00
|
|
|
|
int state_ = std::numeric_limits<int>::min();
|
2022-05-16 15:44:16 +00:00
|
|
|
|
|
2022-05-17 18:08:50 +00:00
|
|
|
|
/// Counts time left on the clock before the current batch of processing
|
|
|
|
|
/// is complete; may be less than zero.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
HalfCycles time_remaining_;
|
2022-05-17 18:08:50 +00:00
|
|
|
|
|
|
|
|
|
/// Current supervisor state, for direct provision to the bus handler.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
int is_supervisor_ = 1;
|
|
|
|
|
|
2022-05-17 18:08:50 +00:00
|
|
|
|
// A decoder for instructions, plus all collected information about the
|
|
|
|
|
// current instruction.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
InstructionSet::M68k::Predecoder<InstructionSet::M68k::Model::M68000> decoder_;
|
|
|
|
|
InstructionSet::M68k::Preinstruction instruction_;
|
|
|
|
|
uint16_t opcode_;
|
2022-05-17 12:26:35 +00:00
|
|
|
|
uint8_t operand_flags_;
|
2022-05-19 20:27:39 +00:00
|
|
|
|
SlicedInt32 instruction_address_;
|
2022-05-16 20:57:40 +00:00
|
|
|
|
|
2022-05-17 18:08:50 +00:00
|
|
|
|
// Register state.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
InstructionSet::M68k::Status status_;
|
|
|
|
|
SlicedInt32 program_counter_;
|
|
|
|
|
SlicedInt32 registers_[16]; // D0–D7 followed by A0–A7.
|
|
|
|
|
SlicedInt32 stack_pointers_[2];
|
|
|
|
|
|
2022-05-17 18:08:50 +00:00
|
|
|
|
/// Current state of the DTACK input.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
bool dtack_ = false;
|
2022-05-17 18:08:50 +00:00
|
|
|
|
/// Current state of the VPA input.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
bool vpa_ = false;
|
2022-05-17 18:08:50 +00:00
|
|
|
|
/// Current state of the BERR input.
|
2022-05-16 20:57:40 +00:00
|
|
|
|
bool berr_ = false;
|
|
|
|
|
|
2022-05-17 18:08:50 +00:00
|
|
|
|
/// Contains the prefetch queue; the most-recently fetched thing is the
|
|
|
|
|
/// low portion of this word, and the thing fetched before that has
|
|
|
|
|
/// proceeded to the high portion.
|
2022-05-17 12:26:35 +00:00
|
|
|
|
SlicedInt32 prefetch_;
|
2022-05-17 18:08:50 +00:00
|
|
|
|
|
|
|
|
|
// Temporary storage for the current instruction's operands
|
|
|
|
|
// and the corresponding effective addresses.
|
|
|
|
|
CPU::SlicedInt32 operand_[2];
|
|
|
|
|
uint32_t effective_address_[2];
|
|
|
|
|
|
|
|
|
|
/// If currently in the wait-for-DTACK state, this indicates where to go
|
|
|
|
|
/// upon receipt of DTACK or VPA. BERR will automatically segue
|
|
|
|
|
/// into the proper exception.
|
|
|
|
|
int post_dtack_state_ = 0;
|
|
|
|
|
|
|
|
|
|
/// The perform state for this operation.
|
|
|
|
|
int perform_state_ = 0;
|
|
|
|
|
|
|
|
|
|
/// When fetching or storing operands, this is the next one to fetch
|
|
|
|
|
/// or store.
|
|
|
|
|
int next_operand_ = 0;
|
2022-05-17 18:51:49 +00:00
|
|
|
|
|
2022-05-17 20:10:20 +00:00
|
|
|
|
/// Storage for a temporary address, which can't be a local because it'll
|
|
|
|
|
/// be used to populate microcycles, which may persist beyond an entry
|
|
|
|
|
/// and exit of run_for (especially between an address announcement, and
|
|
|
|
|
/// a data select).
|
|
|
|
|
uint32_t temporary_address_ = 0;
|
|
|
|
|
|
2022-05-19 20:27:39 +00:00
|
|
|
|
/// A record of the exception to trigger.
|
|
|
|
|
int exception_vector_ = 0;
|
|
|
|
|
|
|
|
|
|
/// Transient storage for exception processing.
|
|
|
|
|
SlicedInt16 captured_status_;
|
|
|
|
|
|
2022-05-17 18:51:49 +00:00
|
|
|
|
// Flow controller... all TODO.
|
|
|
|
|
using Preinstruction = InstructionSet::M68k::Preinstruction;
|
|
|
|
|
|
2022-05-19 19:03:22 +00:00
|
|
|
|
static constexpr uint32_t byte_word_increments[2][8] = {
|
|
|
|
|
{ 1, 1, 1, 1, 1, 1, 1, 2, },
|
|
|
|
|
{ 2, 2, 2, 2, 2, 2, 2, 2, }
|
|
|
|
|
};
|
|
|
|
|
|
2022-05-17 18:51:49 +00:00
|
|
|
|
template <typename IntT> void did_mulu(IntT) {}
|
|
|
|
|
template <typename IntT> void did_muls(IntT) {}
|
2022-05-19 20:27:39 +00:00
|
|
|
|
inline void did_chk(bool, bool);
|
|
|
|
|
inline void did_shift(int) {}
|
2022-05-17 20:10:20 +00:00
|
|
|
|
template <bool did_overflow> void did_divu(uint32_t, uint32_t) {}
|
|
|
|
|
template <bool did_overflow> void did_divs(int32_t, int32_t) {}
|
2022-05-19 20:27:39 +00:00
|
|
|
|
inline void did_bit_op(int) {}
|
2022-05-17 18:51:49 +00:00
|
|
|
|
inline void did_update_status();
|
2022-05-17 20:10:20 +00:00
|
|
|
|
template <typename IntT> void complete_bcc(bool, IntT) {}
|
2022-05-19 20:27:39 +00:00
|
|
|
|
inline void complete_dbcc(bool, bool, int16_t) {}
|
|
|
|
|
inline void bsr(uint32_t) {}
|
|
|
|
|
inline void jsr(uint32_t) {}
|
|
|
|
|
inline void jmp(uint32_t) {}
|
|
|
|
|
inline void rtr() {}
|
|
|
|
|
inline void rte() {}
|
|
|
|
|
inline void rts() {}
|
|
|
|
|
inline void stop() {}
|
|
|
|
|
inline void reset() {}
|
|
|
|
|
inline void link(Preinstruction, uint32_t) {}
|
|
|
|
|
inline void unlink(uint32_t &) {}
|
|
|
|
|
inline void pea(uint32_t) {}
|
|
|
|
|
inline void move_to_usp(uint32_t) {}
|
|
|
|
|
inline void move_from_usp(uint32_t &) {}
|
|
|
|
|
inline void tas(Preinstruction, uint32_t) {}
|
2022-05-17 20:10:20 +00:00
|
|
|
|
template <typename IntT> void movep(Preinstruction, uint32_t, uint32_t) {}
|
|
|
|
|
template <typename IntT> void movem_toM(Preinstruction, uint32_t, uint32_t) {}
|
|
|
|
|
template <typename IntT> void movem_toR(Preinstruction, uint32_t, uint32_t) {}
|
|
|
|
|
template <bool use_current_instruction_pc = true> void raise_exception(int) {}
|
|
|
|
|
|
|
|
|
|
// Some microcycles that will be modified as required and used in the main loop;
|
|
|
|
|
// the semantics of a switch statement make in-place declarations awkward and
|
|
|
|
|
// some of these may persist across multiple calls to run_for.
|
|
|
|
|
Microcycle idle{0};
|
|
|
|
|
|
2022-05-18 19:35:38 +00:00
|
|
|
|
// Read a program word. All accesses via the program counter are word sized.
|
|
|
|
|
Microcycle read_program_announce {
|
|
|
|
|
Microcycle::Read | Microcycle::NewAddress | Microcycle::IsProgram
|
|
|
|
|
};
|
|
|
|
|
Microcycle read_program {
|
|
|
|
|
Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsProgram
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Read a data word or byte.
|
2022-05-19 14:27:51 +00:00
|
|
|
|
Microcycle access_announce {
|
2022-05-17 20:10:20 +00:00
|
|
|
|
Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData
|
|
|
|
|
};
|
2022-05-19 14:27:51 +00:00
|
|
|
|
Microcycle access {
|
2022-05-17 20:10:20 +00:00
|
|
|
|
Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Holding spot when awaiting DTACK/etc.
|
|
|
|
|
Microcycle awaiting_dtack;
|
2022-05-16 15:44:16 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* _8000Mk2Storage_h */
|