1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-19 08:31:11 +00:00

Renamed BusOperation to MachineCycle::Operation.

This commit is contained in:
Thomas Harte 2017-06-17 21:53:45 -04:00
parent b6f51474ff
commit e1a2580b2a
5 changed files with 46 additions and 48 deletions

View File

@ -60,7 +60,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
uint16_t refresh = 0; uint16_t refresh = 0;
uint16_t address = cycle.address ? *cycle.address : 0; uint16_t address = cycle.address ? *cycle.address : 0;
switch(cycle.operation) { switch(cycle.operation) {
case CPU::Z80::BusOperation::Output: case CPU::Z80::MachineCycle::Operation::Output:
set_vsync(false); set_vsync(false);
line_counter_ = 0; line_counter_ = 0;
@ -68,7 +68,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
if(!(address & 1)) nmi_is_enabled_ = is_zx81_; if(!(address & 1)) nmi_is_enabled_ = is_zx81_;
break; break;
case CPU::Z80::BusOperation::Input: { case CPU::Z80::MachineCycle::Operation::Input: {
uint8_t value = 0xff; uint8_t value = 0xff;
if(!(address&1)) { if(!(address&1)) {
set_vsync(true); set_vsync(true);
@ -84,13 +84,13 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
*cycle.value = value; *cycle.value = value;
} break; } break;
case CPU::Z80::BusOperation::Interrupt: case CPU::Z80::MachineCycle::Operation::Interrupt:
line_counter_ = (line_counter_ + 1) & 7; line_counter_ = (line_counter_ + 1) & 7;
*cycle.value = 0xff; *cycle.value = 0xff;
horizontal_counter_ = 0; horizontal_counter_ = 0;
break; break;
case CPU::Z80::BusOperation::ReadOpcode: case CPU::Z80::MachineCycle::Operation::ReadOpcode:
// The ZX80 and 81 signal an interrupt while refresh is active and bit 6 of the refresh // The ZX80 and 81 signal an interrupt while refresh is active and bit 6 of the refresh
// address is low. The Z80 signals a refresh, providing the refresh address during the // address is low. The Z80 signals a refresh, providing the refresh address during the
// final two cycles of an opcode fetch. Therefore communicate a transient signalling // final two cycles of an opcode fetch. Therefore communicate a transient signalling
@ -111,7 +111,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
} }
} }
case CPU::Z80::BusOperation::Read: case CPU::Z80::MachineCycle::Operation::Read:
if(address < ram_base_) { if(address < ram_base_) {
*cycle.value = rom_[address & rom_mask_]; *cycle.value = rom_[address & rom_mask_];
} else { } else {
@ -120,7 +120,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
// If this is an M1 cycle reading from above the 32kb mark and HALT is not // If this is an M1 cycle reading from above the 32kb mark and HALT is not
// currently active, perform a video output and return a NOP. Otherwise, // currently active, perform a video output and return a NOP. Otherwise,
// just return the value as read. // just return the value as read.
if(cycle.operation == CPU::Z80::BusOperation::ReadOpcode && address&0x8000 && !(value & 0x40) && !get_halt_line()) { if(cycle.operation == CPU::Z80::MachineCycle::Operation::ReadOpcode && address&0x8000 && !(value & 0x40) && !get_halt_line()) {
size_t char_address = (size_t)((refresh & 0xff00) | ((value & 0x3f) << 3) | line_counter_); size_t char_address = (size_t)((refresh & 0xff00) | ((value & 0x3f) << 3) | line_counter_);
if(char_address < ram_base_) { if(char_address < ram_base_) {
uint8_t mask = (value & 0x80) ? 0x00 : 0xff; uint8_t mask = (value & 0x80) ? 0x00 : 0xff;
@ -133,7 +133,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
} }
break; break;
case CPU::Z80::BusOperation::Write: case CPU::Z80::MachineCycle::Operation::Write:
if(address >= ram_base_) { if(address >= ram_base_) {
ram_[address & ram_mask_] = *cycle.value; ram_[address & ram_mask_] = *cycle.value;
} }

View File

@ -11,7 +11,7 @@
#import "TestMachine+ForSubclassEyesOnly.h" #import "TestMachine+ForSubclassEyesOnly.h"
@interface CSTestMachineZ80 () @interface CSTestMachineZ80 ()
- (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)time_stamp; - (void)testMachineDidPerformBusOperation:(CPU::Z80::MachineCycle::Operation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)time_stamp;
@end @end
#pragma mark - C++ delegate handlers #pragma mark - C++ delegate handlers
@ -20,7 +20,7 @@ class BusOperationHandler: public CPU::Z80::AllRAMProcessor::MemoryAccessDelegat
public: public:
BusOperationHandler(CSTestMachineZ80 *targetMachine) : target_(targetMachine) {} BusOperationHandler(CSTestMachineZ80 *targetMachine) : target_(targetMachine) {}
void z80_all_ram_processor_did_perform_bus_operation(CPU::Z80::AllRAMProcessor &processor, CPU::Z80::BusOperation operation, uint16_t address, uint8_t value, int time_stamp) { void z80_all_ram_processor_did_perform_bus_operation(CPU::Z80::AllRAMProcessor &processor, CPU::Z80::MachineCycle::Operation operation, uint16_t address, uint8_t value, int time_stamp) {
[target_ testMachineDidPerformBusOperation:operation address:address value:value timeStamp:time_stamp]; [target_ testMachineDidPerformBusOperation:operation address:address value:value timeStamp:time_stamp];
} }
@ -187,36 +187,36 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
_processor->set_memory_access_delegate(captureBusActivity ? _busOperationHandler : nullptr); _processor->set_memory_access_delegate(captureBusActivity ? _busOperationHandler : nullptr);
} }
- (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)timeStamp { - (void)testMachineDidPerformBusOperation:(CPU::Z80::MachineCycle::Operation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)timeStamp {
int length = timeStamp - _lastOpcodeTime; int length = timeStamp - _lastOpcodeTime;
_lastOpcodeTime = timeStamp; _lastOpcodeTime = timeStamp;
if(operation == CPU::Z80::BusOperation::ReadOpcode && length < _timeSeekingReadOpcode) if(operation == CPU::Z80::MachineCycle::Operation::ReadOpcode && length < _timeSeekingReadOpcode)
_isAtReadOpcode = YES; _isAtReadOpcode = YES;
if(self.captureBusActivity) { if(self.captureBusActivity) {
CSTestMachineZ80BusOperationCapture *capture = [[CSTestMachineZ80BusOperationCapture alloc] init]; CSTestMachineZ80BusOperationCapture *capture = [[CSTestMachineZ80BusOperationCapture alloc] init];
switch(operation) { switch(operation) {
case CPU::Z80::BusOperation::Write: case CPU::Z80::MachineCycle::Operation::Write:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationWrite; capture.operation = CSTestMachineZ80BusOperationCaptureOperationWrite;
break; break;
case CPU::Z80::BusOperation::Read: case CPU::Z80::MachineCycle::Operation::Read:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationRead; capture.operation = CSTestMachineZ80BusOperationCaptureOperationRead;
break; break;
case CPU::Z80::BusOperation::ReadOpcode: case CPU::Z80::MachineCycle::Operation::ReadOpcode:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationReadOpcode; capture.operation = CSTestMachineZ80BusOperationCaptureOperationReadOpcode;
break; break;
case CPU::Z80::BusOperation::Input: case CPU::Z80::MachineCycle::Operation::Input:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortRead; capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortRead;
break; break;
case CPU::Z80::BusOperation::Output: case CPU::Z80::MachineCycle::Operation::Output:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortWrite; capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortWrite;
break; break;
case CPU::Z80::BusOperation::Internal: case CPU::Z80::MachineCycle::Operation::Internal:
capture.operation = CSTestMachineZ80BusOperationCaptureOperationInternalOperation; capture.operation = CSTestMachineZ80BusOperationCaptureOperationInternalOperation;
break; break;

View File

@ -62,17 +62,15 @@ enum Flag: uint8_t {
Subclasses will be given the task of performing bus operations, allowing them to provide whatever interface they like Subclasses will be given the task of performing bus operations, allowing them to provide whatever interface they like
between a Z80 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested. between a Z80 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.
*/ */
enum BusOperation {
ReadOpcode = 0,
Read, Write,
Input, Output,
Interrupt,
BusAcknowledge,
Internal
};
struct MachineCycle { struct MachineCycle {
BusOperation operation; enum Operation {
ReadOpcode = 0,
Read, Write,
Input, Output,
Interrupt,
BusAcknowledge,
Internal
} operation;
int length; int length;
uint16_t *address; uint16_t *address;
uint8_t *value; uint8_t *value;
@ -242,14 +240,14 @@ template <class T> class Processor {
#define INC16(r) {(&r == &pc_) ? MicroOp::IncrementPC : MicroOp::Increment16, &r.full} #define INC16(r) {(&r == &pc_) ? MicroOp::IncrementPC : MicroOp::Increment16, &r.full}
/// Fetches into x from address y, and then increments y. /// Fetches into x from address y, and then increments y.
#define FETCH(x, y) {MicroOp::BusOperation, nullptr, nullptr, {Read, 3, &y.full, &x}}, INC16(y) #define FETCH(x, y) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Read, 3, &y.full, &x}}, INC16(y)
/// Fetches into x from address y. /// Fetches into x from address y.
#define FETCHL(x, y) {MicroOp::BusOperation, nullptr, nullptr, {Read, 3, &y.full, &x}} #define FETCHL(x, y) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Read, 3, &y.full, &x}}
/// Stores x to address y, and then increments y. /// Stores x to address y, and then increments y.
#define STORE(x, y) {MicroOp::BusOperation, nullptr, nullptr, {Write, 3, &y.full, &x}}, {MicroOp::Increment16, &y.full} #define STORE(x, y) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Write, 3, &y.full, &x}}, {MicroOp::Increment16, &y.full}
/// Stores x to address y. /// Stores x to address y.
#define STOREL(x, y) {MicroOp::BusOperation, nullptr, nullptr, {Write, 3, &y.full, &x}} #define STOREL(x, y) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Write, 3, &y.full, &x}}
/// Fetches the 16-bit quantity x from address y, incrementing y twice. /// Fetches the 16-bit quantity x from address y, incrementing y twice.
#define FETCH16(x, y) FETCH(x.bytes.low, y), FETCH(x.bytes.high, y) #define FETCH16(x, y) FETCH(x.bytes.low, y), FETCH(x.bytes.high, y)
@ -260,10 +258,10 @@ template <class T> class Processor {
#define STORE16L(x, y) STORE(x.bytes.low, y), STOREL(x.bytes.high, y) #define STORE16L(x, y) STORE(x.bytes.low, y), STOREL(x.bytes.high, y)
/// Outputs the 8-bit value to the 16-bit port /// Outputs the 8-bit value to the 16-bit port
#define OUT(port, value) {MicroOp::BusOperation, nullptr, nullptr, {Output, 4, &port.full, &value}} #define OUT(port, value) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Output, 4, &port.full, &value}}
/// Inputs the 8-bit value from the 16-bit port /// Inputs the 8-bit value from the 16-bit port
#define IN(port, value) {MicroOp::BusOperation, nullptr, nullptr, {Input, 4, &port.full, &value}} #define IN(port, value) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Input, 4, &port.full, &value}}
#define PUSH(x) {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.high, sp_), {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.low, sp_) #define PUSH(x) {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.high, sp_), {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.low, sp_)
#define POP(x) FETCHL(x.bytes.low, sp_), {MicroOp::Increment16, &sp_.full}, FETCHL(x.bytes.high, sp_), {MicroOp::Increment16, &sp_.full} #define POP(x) FETCHL(x.bytes.low, sp_), {MicroOp::Increment16, &sp_.full}, FETCHL(x.bytes.high, sp_), {MicroOp::Increment16, &sp_.full}
@ -327,7 +325,7 @@ template <class T> class Processor {
#define ADC16(d, s) Program(WAIT(4), WAIT(3), {MicroOp::ADC16, &s.full, &d.full}) #define ADC16(d, s) Program(WAIT(4), WAIT(3), {MicroOp::ADC16, &s.full, &d.full})
#define SBC16(d, s) Program(WAIT(4), WAIT(3), {MicroOp::SBC16, &s.full, &d.full}) #define SBC16(d, s) Program(WAIT(4), WAIT(3), {MicroOp::SBC16, &s.full, &d.full})
#define WAIT(n) {MicroOp::BusOperation, nullptr, nullptr, {Internal, n} } #define WAIT(n) {MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Internal, n} }
#define Program(...) { __VA_ARGS__, {MicroOp::MoveToNextProgram} } #define Program(...) { __VA_ARGS__, {MicroOp::MoveToNextProgram} }
#define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation || n == MicroOp::DecodeOperationNoRChange) #define isTerminal(n) (n == MicroOp::MoveToNextProgram || n == MicroOp::DecodeOperation || n == MicroOp::DecodeOperationNoRChange)
@ -655,7 +653,7 @@ template <class T> class Processor {
void assemble_fetch_decode_execute(InstructionPage &target, int length) { void assemble_fetch_decode_execute(InstructionPage &target, int length) {
const MicroOp fetch_decode_execute[] = { const MicroOp fetch_decode_execute[] = {
{ MicroOp::BusOperation, nullptr, nullptr, {(length == 4) ? ReadOpcode : Read, length, &pc_.full, &operation_}}, { MicroOp::BusOperation, nullptr, nullptr, {(length == 4) ? MachineCycle::ReadOpcode : MachineCycle::Read, length, &pc_.full, &operation_}},
{ MicroOp::DecodeOperation } { MicroOp::DecodeOperation }
}; };
copy_program(fetch_decode_execute, target.fetch_decode_execute); copy_program(fetch_decode_execute, target.fetch_decode_execute);
@ -711,26 +709,26 @@ template <class T> class Processor {
MicroOp reset_program[] = Program(WAIT(3), {MicroOp::Reset}); MicroOp reset_program[] = Program(WAIT(3), {MicroOp::Reset});
MicroOp nmi_program[] = { MicroOp nmi_program[] = {
{ MicroOp::BeginNMI }, { MicroOp::BeginNMI },
{ MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, 5, &pc_.full, &operation_}}, { MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::ReadOpcode, 5, &pc_.full, &operation_}},
PUSH(pc_), PUSH(pc_),
{ MicroOp::JumpTo66, nullptr, nullptr}, { MicroOp::JumpTo66, nullptr, nullptr},
{ MicroOp::MoveToNextProgram } { MicroOp::MoveToNextProgram }
}; };
MicroOp irq_mode0_program[] = { MicroOp irq_mode0_program[] = {
{ MicroOp::BeginIRQMode0 }, { MicroOp::BeginIRQMode0 },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 6, nullptr, &operation_}}, { MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Operation::Interrupt, 6, nullptr, &operation_}},
{ MicroOp::DecodeOperationNoRChange } { MicroOp::DecodeOperationNoRChange }
}; };
MicroOp irq_mode1_program[] = { MicroOp irq_mode1_program[] = {
{ MicroOp::BeginIRQ }, { MicroOp::BeginIRQ },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &operation_}}, { MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Operation::Interrupt, 7, nullptr, &operation_}},
PUSH(pc_), PUSH(pc_),
{ MicroOp::Move16, &temp16_.full, &pc_.full }, { MicroOp::Move16, &temp16_.full, &pc_.full },
{ MicroOp::MoveToNextProgram } { MicroOp::MoveToNextProgram }
}; };
MicroOp irq_mode2_program[] = { MicroOp irq_mode2_program[] = {
{ MicroOp::BeginIRQ }, { MicroOp::BeginIRQ },
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &temp16_.bytes.low}}, { MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Operation::Interrupt, 7, nullptr, &temp16_.bytes.low}},
PUSH(pc_), PUSH(pc_),
{ MicroOp::Move8, &ir_.bytes.high, &temp16_.bytes.high }, { MicroOp::Move8, &ir_.bytes.high, &temp16_.bytes.high },
FETCH16L(pc_, temp16_), FETCH16L(pc_, temp16_),
@ -781,7 +779,7 @@ template <class T> class Processor {
while(1) { while(1) {
while(bus_request_line_) { while(bus_request_line_) {
static MachineCycle bus_acknowledge_cycle = {BusOperation::BusAcknowledge, 1}; static MachineCycle bus_acknowledge_cycle = {MachineCycle::Operation::BusAcknowledge, 1};
number_of_cycles_ -= static_cast<T *>(this)->perform_machine_cycle(bus_acknowledge_cycle) + 1; number_of_cycles_ -= static_cast<T *>(this)->perform_machine_cycle(bus_acknowledge_cycle) + 1;
if(!number_of_cycles_) { if(!number_of_cycles_) {
static_cast<T *>(this)->flush(); static_cast<T *>(this)->flush();

View File

@ -20,30 +20,30 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor<Concrete
completed_cycles += cycle.length; completed_cycles += cycle.length;
uint16_t address = cycle.address ? *cycle.address : 0x0000; uint16_t address = cycle.address ? *cycle.address : 0x0000;
switch(cycle.operation) { switch(cycle.operation) {
case BusOperation::ReadOpcode: case MachineCycle::Operation::ReadOpcode:
// printf("! "); // printf("! ");
check_address_for_trap(address); check_address_for_trap(address);
case BusOperation::Read: case MachineCycle::Operation::Read:
// printf("r %04x [%02x] AF:%04x BC:%04x DE:%04x HL:%04x SP:%04x\n", address, memory_[address], get_value_of_register(CPU::Z80::Register::AF), get_value_of_register(CPU::Z80::Register::BC), get_value_of_register(CPU::Z80::Register::DE), get_value_of_register(CPU::Z80::Register::HL), get_value_of_register(CPU::Z80::Register::StackPointer)); // printf("r %04x [%02x] AF:%04x BC:%04x DE:%04x HL:%04x SP:%04x\n", address, memory_[address], get_value_of_register(CPU::Z80::Register::AF), get_value_of_register(CPU::Z80::Register::BC), get_value_of_register(CPU::Z80::Register::DE), get_value_of_register(CPU::Z80::Register::HL), get_value_of_register(CPU::Z80::Register::StackPointer));
*cycle.value = memory_[address]; *cycle.value = memory_[address];
break; break;
case BusOperation::Write: case MachineCycle::Operation::Write:
// printf("w %04x\n", address); // printf("w %04x\n", address);
memory_[address] = *cycle.value; memory_[address] = *cycle.value;
break; break;
case BusOperation::Output: case MachineCycle::Operation::Output:
break; break;
case BusOperation::Input: case MachineCycle::Operation::Input:
// This logic is selected specifically because it seems to match // This logic is selected specifically because it seems to match
// the FUSE unit tests. It might need factoring out. // the FUSE unit tests. It might need factoring out.
*cycle.value = address >> 8; *cycle.value = address >> 8;
break; break;
case BusOperation::Internal: case MachineCycle::Operation::Internal:
break; break;
case BusOperation::Interrupt: case MachineCycle::Operation::Interrupt:
// A pick that means LD HL, (nn) if interpreted as an instruction but is otherwise // A pick that means LD HL, (nn) if interpreted as an instruction but is otherwise
// arbitrary. // arbitrary.
*cycle.value = 0x21; *cycle.value = 0x21;

View File

@ -22,7 +22,7 @@ class AllRAMProcessor:
static AllRAMProcessor *Processor(); static AllRAMProcessor *Processor();
struct MemoryAccessDelegate { struct MemoryAccessDelegate {
virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, BusOperation operation, uint16_t address, uint8_t value, int time_stamp) = 0; virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, MachineCycle::Operation operation, uint16_t address, uint8_t value, int time_stamp) = 0;
}; };
inline void set_memory_access_delegate(MemoryAccessDelegate *delegate) { inline void set_memory_access_delegate(MemoryAccessDelegate *delegate) {
delegate_ = delegate; delegate_ = delegate;