2022-04-29 21:12:06 +00:00
|
|
|
|
//
|
|
|
|
|
// Executor.hpp
|
|
|
|
|
// Clock Signal
|
|
|
|
|
//
|
|
|
|
|
// Created by Thomas Harte on 29/04/2022.
|
|
|
|
|
// Copyright © 2022 Thomas Harte. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#ifndef InstructionSets_M68k_Executor_hpp
|
|
|
|
|
#define InstructionSets_M68k_Executor_hpp
|
|
|
|
|
|
|
|
|
|
#include "Decoder.hpp"
|
|
|
|
|
#include "Instruction.hpp"
|
|
|
|
|
#include "Model.hpp"
|
|
|
|
|
#include "Perform.hpp"
|
|
|
|
|
#include "Status.hpp"
|
|
|
|
|
|
|
|
|
|
namespace InstructionSet {
|
|
|
|
|
namespace M68k {
|
|
|
|
|
|
|
|
|
|
struct BusHandler {
|
|
|
|
|
template <typename IntT> void write(uint32_t address, IntT value);
|
|
|
|
|
template <typename IntT> IntT read(uint32_t address);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Ties together the decoder, sequencer and performer to provide an executor for 680x0 instruction streams.
|
|
|
|
|
/// As is standard for these executors, no bus- or cache-level fidelity to any real 680x0 is attempted. This is
|
|
|
|
|
/// simply an executor of 680x0 code.
|
|
|
|
|
template <Model model, typename BusHandler> class Executor {
|
|
|
|
|
public:
|
|
|
|
|
Executor(BusHandler &);
|
|
|
|
|
|
|
|
|
|
/// Executes the number of instructions specified;
|
|
|
|
|
/// other events — such as initial reset or branching
|
|
|
|
|
/// to exceptions — may be zero costed, and interrupts
|
|
|
|
|
/// will not necessarily take effect immediately when signalled.
|
|
|
|
|
void run_for_instructions(int);
|
|
|
|
|
|
2022-05-02 11:45:07 +00:00
|
|
|
|
|
|
|
|
|
// Flow control.
|
|
|
|
|
void consume_cycles(int) {}
|
|
|
|
|
void raise_exception(int);
|
|
|
|
|
void stop();
|
|
|
|
|
void set_pc(uint32_t);
|
|
|
|
|
void add_pc(uint32_t);
|
2022-05-03 01:27:58 +00:00
|
|
|
|
void decline_branch() {}
|
|
|
|
|
void did_update_status();
|
2022-05-04 12:26:11 +00:00
|
|
|
|
|
2022-05-03 19:32:54 +00:00
|
|
|
|
void bsr(uint32_t offset);
|
2022-05-03 19:49:55 +00:00
|
|
|
|
void jsr(uint32_t offset);
|
2022-05-04 12:26:11 +00:00
|
|
|
|
void link(uint32_t &address, uint32_t offset);
|
|
|
|
|
void unlink(uint32_t &address);
|
2022-05-05 16:27:36 +00:00
|
|
|
|
template <typename IntT> void movep(Preinstruction instruction, uint32_t source, uint32_t dest);
|
2022-05-06 13:45:06 +00:00
|
|
|
|
template <typename IntT> void movem_toM(Preinstruction instruction, uint32_t source, uint32_t dest);
|
|
|
|
|
template <typename IntT> void movem_toR(Preinstruction instruction, uint32_t source, uint32_t dest);
|
2022-05-06 15:33:57 +00:00
|
|
|
|
void pea(uint32_t address);
|
2022-05-02 11:45:07 +00:00
|
|
|
|
|
2022-05-02 16:57:45 +00:00
|
|
|
|
// TODO: ownership of this shouldn't be here.
|
|
|
|
|
struct Registers {
|
|
|
|
|
uint32_t data[8], address[7];
|
|
|
|
|
uint32_t user_stack_pointer;
|
|
|
|
|
uint32_t supervisor_stack_pointer;
|
|
|
|
|
uint16_t status;
|
|
|
|
|
uint32_t program_counter;
|
|
|
|
|
};
|
|
|
|
|
Registers get_state();
|
|
|
|
|
void set_state(const Registers &);
|
|
|
|
|
|
2022-04-29 21:12:06 +00:00
|
|
|
|
private:
|
|
|
|
|
BusHandler &bus_handler_;
|
|
|
|
|
Predecoder<model> decoder_;
|
|
|
|
|
|
|
|
|
|
void reset();
|
2022-05-01 17:00:20 +00:00
|
|
|
|
struct EffectiveAddress {
|
2022-05-01 17:09:28 +00:00
|
|
|
|
CPU::SlicedInt32 value;
|
2022-05-01 19:12:13 +00:00
|
|
|
|
bool requires_fetch;
|
2022-05-01 17:00:20 +00:00
|
|
|
|
};
|
|
|
|
|
EffectiveAddress calculate_effective_address(Preinstruction instruction, uint16_t opcode, int index);
|
2022-04-29 21:12:06 +00:00
|
|
|
|
|
2022-05-01 17:09:28 +00:00
|
|
|
|
void read(DataSize size, uint32_t address, CPU::SlicedInt32 &value);
|
|
|
|
|
void write(DataSize size, uint32_t address, CPU::SlicedInt32 value);
|
2022-05-01 19:10:54 +00:00
|
|
|
|
template <typename IntT> IntT read_pc();
|
|
|
|
|
uint32_t index_8bitdisplacement();
|
2022-05-01 17:09:28 +00:00
|
|
|
|
|
2022-04-29 21:12:06 +00:00
|
|
|
|
// Processor state.
|
|
|
|
|
Status status_;
|
|
|
|
|
CPU::SlicedInt32 program_counter_;
|
2022-05-05 19:31:59 +00:00
|
|
|
|
CPU::SlicedInt32 registers_[16]; // D0–D8, followed by A0–A8.
|
2022-04-30 12:38:28 +00:00
|
|
|
|
CPU::SlicedInt32 stack_pointers_[2];
|
2022-05-01 19:10:54 +00:00
|
|
|
|
uint32_t instruction_address_;
|
2022-05-03 01:27:58 +00:00
|
|
|
|
int active_stack_pointer_ = 0;
|
2022-05-01 19:10:54 +00:00
|
|
|
|
|
|
|
|
|
// A lookup table to ensure that A7 is adjusted by 2 rather than 1 in
|
|
|
|
|
// postincrement and predecrement mode.
|
|
|
|
|
static constexpr uint32_t byte_increments[] = {
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 2
|
|
|
|
|
};
|
2022-04-29 21:12:06 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-01 19:10:54 +00:00
|
|
|
|
#include "Implementation/ExecutorImplementation.hpp"
|
|
|
|
|
|
2022-04-29 21:12:06 +00:00
|
|
|
|
#endif /* InstructionSets_M68k_Executor_hpp */
|