1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +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_wait_line> void Processor <T, uses_bus_request, uses_wait_line>
::run_for(const HalfCycles cycles) {
#define advance_operation() \
pc_increment_ = 1; \
if(last_request_status_) { \
halt_mask_ = 0xff; \
if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) { \
request_status_ &= ~Interrupt::PowerOn; \
scheduled_program_counter_ = reset_program_.data(); \
} else if(last_request_status_ & Interrupt::NMI) { \
request_status_ &= ~Interrupt::NMI; \
scheduled_program_counter_ = nmi_program_.data(); \
} else if(last_request_status_ & Interrupt::IRQ) { \
scheduled_program_counter_ = irq_program_[interrupt_mode_].data(); \
} \
} else { \
current_instruction_page_ = &base_page_; \
scheduled_program_counter_ = base_page_.fetch_decode_execute_data; \
}
/// Schedules the next concrete block of work for the CPU, whatever that may be:
/// performing the reset, NMI or IRQ sequences, or fetching a new instruction.
const auto advance_operation = [&] {
pc_increment_ = 1;
if(last_request_status_) {
halt_mask_ = 0xff;
if(last_request_status_ & (Interrupt::PowerOn | Interrupt::Reset)) {
request_status_ &= ~Interrupt::PowerOn;
scheduled_program_counter_ = reset_program_.data();
} else if(last_request_status_ & Interrupt::NMI) {
request_status_ &= ~Interrupt::NMI;
scheduled_program_counter_ = nmi_program_.data();
} else if(last_request_status_ & Interrupt::IRQ) {
scheduled_program_counter_ = irq_program_[interrupt_mode_].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;
if(!scheduled_program_counter_) {
@ -42,7 +59,6 @@ template < class T,
}
while(1) {
do_bus_acknowledge:
while(uses_bus_request && bus_request_line_) {
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_;
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) {
case MicroOp::BusOperation:
if(number_of_cycles_ < operation->machine_cycle.length) {
@ -449,12 +456,9 @@ template < class T,
// MARK: - Exchange
#define swap(a, b) temp = a.full; a.full = b.full; b.full = temp;
case MicroOp::ExDEHL: {
uint16_t temp;
swap(de_, hl_);
} break;
case MicroOp::ExDEHL:
std::swap(de_, hl_);
break;
case MicroOp::ExAFAFDash: {
const uint8_t a = a_;
@ -465,14 +469,11 @@ template < class T,
af_dash_.halves.low = f;
} break;
case MicroOp::EXX: {
uint16_t temp;
swap(de_, de_dash_);
swap(bc_, bc_dash_);
swap(hl_, hl_dash_);
} break;
#undef swap
case MicroOp::EXX:
std::swap(de_, de_dash_);
std::swap(bc_, bc_dash_);
std::swap(hl_, hl_dash_);
break;
// MARK: - Repetition
@ -890,7 +891,6 @@ template < class T,
case MicroOp::IndexedPlaceHolder:
return;
}
#undef set_parity
}
}
@ -926,8 +926,6 @@ template < class T,
return wait_line_;
}
#define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation)
template < class T,
bool uses_bus_request,
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.
for(int c = 0; c < 256; c++) {
std::size_t length = 0;
while(!isTerminal(table[c][length].type)) length++;
while(!is_terminal(table[c][length].type)) length++;
length++;
lengths[c] = 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>
::copy_program(const MicroOp *source, std::vector<MicroOp> &destination) {
std::size_t length = 0;
while(!isTerminal(source[length].type)) length++;
while(!is_terminal(source[length].type)) length++;
std::size_t pointer = 0;
while(true) {
// 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]);
if(isTerminal(source[pointer].type)) break;
if(is_terminal(source[pointer].type)) break;
pointer++;
}
}
#undef isTerminal
bool ProcessorBase::get_halt_line() const {
return halt_mask_ == 0x00;
}

View File

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

View File

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