1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 18:55:48 +00:00

Eliminate easy macros from Z80 implementation.

This commit is contained in:
Thomas Harte 2024-01-16 09:43:41 -05:00
parent 9990725cfb
commit de038fe28f
3 changed files with 49 additions and 49 deletions

View File

@ -18,23 +18,40 @@ template < class T,
bool uses_bus_request, bool uses_bus_request,
bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line> bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line>
::run_for(const HalfCycles cycles) { ::run_for(const HalfCycles cycles) {
#define advance_operation() \
pc_increment_ = 1; \ /// Schedules the next concrete block of work for the CPU, whatever that may be:
if(last_request_status_) { \ /// performing the reset, NMI or IRQ sequences, or fetching a new instruction.
halt_mask_ = 0xff; \ const auto advance_operation = [&] {
if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) { \ pc_increment_ = 1;
request_status_ &= ~Interrupt::PowerOn; \ if(last_request_status_) {
scheduled_program_counter_ = reset_program_.data(); \ halt_mask_ = 0xff;
} else if(last_request_status_ & Interrupt::NMI) { \ if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) {
request_status_ &= ~Interrupt::NMI; \ request_status_ &= ~Interrupt::PowerOn;
scheduled_program_counter_ = nmi_program_.data(); \ scheduled_program_counter_ = reset_program_.data();
} else if(last_request_status_ & Interrupt::IRQ) { \ } else if(last_request_status_ & Interrupt::NMI) {
scheduled_program_counter_ = irq_program_[interrupt_mode_].data(); \ request_status_ &= ~Interrupt::NMI;
} \ scheduled_program_counter_ = nmi_program_.data();
} else { \ } else if(last_request_status_ & Interrupt::IRQ) {
current_instruction_page_ = &base_page_; \ scheduled_program_counter_ = irq_program_[interrupt_mode_].data();
scheduled_program_counter_ = base_page_.fetch_decode_execute_data; \ }
} } else {
current_instruction_page_ = &base_page_;
scheduled_program_counter_ = base_page_.fetch_decode_execute_data;
}
};
/// Indicates that the ALU was used in this operation; this affects flag output in future SCF and CCFs.
const auto set_did_compute_flags = [&] {
flag_adjustment_history_ |= 1;
};
/// Computes parity for @c v, leaving it bit 2 of parity_overflow_result_; the other bits are undefined.
const auto set_parity = [&](uint8_t v) {
parity_overflow_result_ = uint8_t(v^1);
parity_overflow_result_ ^= parity_overflow_result_ >> 4;
parity_overflow_result_ ^= parity_overflow_result_ << 2;
parity_overflow_result_ ^= parity_overflow_result_ >> 1;
};
number_of_cycles_ += cycles; number_of_cycles_ += cycles;
if(!scheduled_program_counter_) { if(!scheduled_program_counter_) {
@ -42,7 +59,6 @@ template < class T,
} }
while(1) { while(1) {
do_bus_acknowledge: do_bus_acknowledge:
while(uses_bus_request && bus_request_line_) { while(uses_bus_request && bus_request_line_) {
static PartialMachineCycle bus_acknowledge_cycle = {PartialMachineCycle::BusAcknowledge, HalfCycles(2), nullptr, nullptr, false}; static PartialMachineCycle bus_acknowledge_cycle = {PartialMachineCycle::BusAcknowledge, HalfCycles(2), nullptr, nullptr, false};
@ -56,15 +72,6 @@ template < class T,
const MicroOp *const operation = scheduled_program_counter_; const MicroOp *const operation = scheduled_program_counter_;
scheduled_program_counter_++; scheduled_program_counter_++;
#define set_did_compute_flags() \
flag_adjustment_history_ |= 1;
#define set_parity(v) \
parity_overflow_result_ = uint8_t(v^1);\
parity_overflow_result_ ^= parity_overflow_result_ >> 4;\
parity_overflow_result_ ^= parity_overflow_result_ << 2;\
parity_overflow_result_ ^= parity_overflow_result_ >> 1;
switch(operation->type) { switch(operation->type) {
case MicroOp::BusOperation: case MicroOp::BusOperation:
if(number_of_cycles_ < operation->machine_cycle.length) { if(number_of_cycles_ < operation->machine_cycle.length) {
@ -449,12 +456,9 @@ template < class T,
// MARK: - Exchange // MARK: - Exchange
#define swap(a, b) temp = a.full; a.full = b.full; b.full = temp; case MicroOp::ExDEHL:
std::swap(de_, hl_);
case MicroOp::ExDEHL: { break;
uint16_t temp;
swap(de_, hl_);
} break;
case MicroOp::ExAFAFDash: { case MicroOp::ExAFAFDash: {
const uint8_t a = a_; const uint8_t a = a_;
@ -465,14 +469,11 @@ template < class T,
af_dash_.halves.low = f; af_dash_.halves.low = f;
} break; } break;
case MicroOp::EXX: { case MicroOp::EXX:
uint16_t temp; std::swap(de_, de_dash_);
swap(de_, de_dash_); std::swap(bc_, bc_dash_);
swap(bc_, bc_dash_); std::swap(hl_, hl_dash_);
swap(hl_, hl_dash_); break;
} break;
#undef swap
// MARK: - Repetition // MARK: - Repetition
@ -890,7 +891,6 @@ template < class T,
case MicroOp::IndexedPlaceHolder: case MicroOp::IndexedPlaceHolder:
return; return;
} }
#undef set_parity
} }
} }
@ -926,8 +926,6 @@ template < class T,
return wait_line_; return wait_line_;
} }
#define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation)
template < class T, template < class T,
bool uses_bus_request, bool uses_bus_request,
bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line> bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line>
@ -938,7 +936,7 @@ template < class T,
// Count number of micro-ops required. // Count number of micro-ops required.
for(int c = 0; c < 256; c++) { for(int c = 0; c < 256; c++) {
std::size_t length = 0; std::size_t length = 0;
while(!isTerminal(table[c][length].type)) length++; while(!is_terminal(table[c][length].type)) length++;
length++; length++;
lengths[c] = length; lengths[c] = length;
number_of_micro_ops += length; number_of_micro_ops += length;
@ -995,7 +993,7 @@ template < class T,
bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line> bool uses_wait_line> void Processor <T, uses_bus_request, uses_wait_line>
::copy_program(const MicroOp *source, std::vector<MicroOp> &destination) { ::copy_program(const MicroOp *source, std::vector<MicroOp> &destination) {
std::size_t length = 0; std::size_t length = 0;
while(!isTerminal(source[length].type)) length++; while(!is_terminal(source[length].type)) length++;
std::size_t pointer = 0; std::size_t pointer = 0;
while(true) { while(true) {
// TODO: This test is duplicated from assemble_page; can a better factoring be found? // TODO: This test is duplicated from assemble_page; can a better factoring be found?
@ -1006,13 +1004,11 @@ template < class T,
} }
destination.emplace_back(source[pointer]); destination.emplace_back(source[pointer]);
if(isTerminal(source[pointer].type)) break; if(is_terminal(source[pointer].type)) break;
pointer++; pointer++;
} }
} }
#undef isTerminal
bool ProcessorBase::get_halt_line() const { bool ProcessorBase::get_halt_line() const {
return halt_mask_ == 0x00; return halt_mask_ == 0x00;
} }

View File

@ -115,6 +115,9 @@ class ProcessorStorage {
void *destination = nullptr; void *destination = nullptr;
PartialMachineCycle machine_cycle{}; PartialMachineCycle machine_cycle{};
}; };
static constexpr bool is_terminal(MicroOp::Type type) {
return type == MicroOp::MoveToNextProgram || type == MicroOp::DecodeOperation;
}
struct InstructionPage { struct InstructionPage {
std::vector<MicroOp *> instructions; std::vector<MicroOp *> instructions;

View File

@ -9,6 +9,7 @@
#ifndef Z80_hpp #ifndef Z80_hpp
#define Z80_hpp #define Z80_hpp
#include <algorithm>
#include <cassert> #include <cassert>
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>