mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-28 21:49:27 +00:00
Eliminate easy macros from Z80 implementation.
This commit is contained in:
parent
9990725cfb
commit
de038fe28f
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user