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:
parent
b6f51474ff
commit
e1a2580b2a
@ -60,7 +60,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
|
||||
uint16_t refresh = 0;
|
||||
uint16_t address = cycle.address ? *cycle.address : 0;
|
||||
switch(cycle.operation) {
|
||||
case CPU::Z80::BusOperation::Output:
|
||||
case CPU::Z80::MachineCycle::Operation::Output:
|
||||
set_vsync(false);
|
||||
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_;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Input: {
|
||||
case CPU::Z80::MachineCycle::Operation::Input: {
|
||||
uint8_t value = 0xff;
|
||||
if(!(address&1)) {
|
||||
set_vsync(true);
|
||||
@ -84,13 +84,13 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
|
||||
*cycle.value = value;
|
||||
} break;
|
||||
|
||||
case CPU::Z80::BusOperation::Interrupt:
|
||||
case CPU::Z80::MachineCycle::Operation::Interrupt:
|
||||
line_counter_ = (line_counter_ + 1) & 7;
|
||||
*cycle.value = 0xff;
|
||||
horizontal_counter_ = 0;
|
||||
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
|
||||
// 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
|
||||
@ -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_) {
|
||||
*cycle.value = rom_[address & rom_mask_];
|
||||
} 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
|
||||
// currently active, perform a video output and return a NOP. Otherwise,
|
||||
// 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_);
|
||||
if(char_address < ram_base_) {
|
||||
uint8_t mask = (value & 0x80) ? 0x00 : 0xff;
|
||||
@ -133,7 +133,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Write:
|
||||
case CPU::Z80::MachineCycle::Operation::Write:
|
||||
if(address >= ram_base_) {
|
||||
ram_[address & ram_mask_] = *cycle.value;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#import "TestMachine+ForSubclassEyesOnly.h"
|
||||
|
||||
@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
|
||||
|
||||
#pragma mark - C++ delegate handlers
|
||||
@ -20,7 +20,7 @@ class BusOperationHandler: public CPU::Z80::AllRAMProcessor::MemoryAccessDelegat
|
||||
public:
|
||||
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];
|
||||
}
|
||||
|
||||
@ -187,36 +187,36 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
_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;
|
||||
_lastOpcodeTime = timeStamp;
|
||||
if(operation == CPU::Z80::BusOperation::ReadOpcode && length < _timeSeekingReadOpcode)
|
||||
if(operation == CPU::Z80::MachineCycle::Operation::ReadOpcode && length < _timeSeekingReadOpcode)
|
||||
_isAtReadOpcode = YES;
|
||||
|
||||
if(self.captureBusActivity) {
|
||||
CSTestMachineZ80BusOperationCapture *capture = [[CSTestMachineZ80BusOperationCapture alloc] init];
|
||||
switch(operation) {
|
||||
case CPU::Z80::BusOperation::Write:
|
||||
case CPU::Z80::MachineCycle::Operation::Write:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationWrite;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Read:
|
||||
case CPU::Z80::MachineCycle::Operation::Read:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationRead;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::ReadOpcode:
|
||||
case CPU::Z80::MachineCycle::Operation::ReadOpcode:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationReadOpcode;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Input:
|
||||
case CPU::Z80::MachineCycle::Operation::Input:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortRead;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Output:
|
||||
case CPU::Z80::MachineCycle::Operation::Output:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationPortWrite;
|
||||
break;
|
||||
|
||||
case CPU::Z80::BusOperation::Internal:
|
||||
case CPU::Z80::MachineCycle::Operation::Internal:
|
||||
capture.operation = CSTestMachineZ80BusOperationCaptureOperationInternalOperation;
|
||||
break;
|
||||
|
||||
|
@ -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
|
||||
between a Z80 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.
|
||||
*/
|
||||
enum BusOperation {
|
||||
struct MachineCycle {
|
||||
enum Operation {
|
||||
ReadOpcode = 0,
|
||||
Read, Write,
|
||||
Input, Output,
|
||||
Interrupt,
|
||||
BusAcknowledge,
|
||||
Internal
|
||||
};
|
||||
|
||||
struct MachineCycle {
|
||||
BusOperation operation;
|
||||
} operation;
|
||||
int length;
|
||||
uint16_t *address;
|
||||
uint8_t *value;
|
||||
@ -242,14 +240,14 @@ template <class T> class Processor {
|
||||
#define INC16(r) {(&r == &pc_) ? MicroOp::IncrementPC : MicroOp::Increment16, &r.full}
|
||||
|
||||
/// 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.
|
||||
#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.
|
||||
#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.
|
||||
#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.
|
||||
#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)
|
||||
|
||||
/// 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
|
||||
#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 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 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 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) {
|
||||
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 }
|
||||
};
|
||||
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 nmi_program[] = {
|
||||
{ MicroOp::BeginNMI },
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, 5, &pc_.full, &operation_}},
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::ReadOpcode, 5, &pc_.full, &operation_}},
|
||||
PUSH(pc_),
|
||||
{ MicroOp::JumpTo66, nullptr, nullptr},
|
||||
{ MicroOp::MoveToNextProgram }
|
||||
};
|
||||
MicroOp irq_mode0_program[] = {
|
||||
{ MicroOp::BeginIRQMode0 },
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 6, nullptr, &operation_}},
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Operation::Interrupt, 6, nullptr, &operation_}},
|
||||
{ MicroOp::DecodeOperationNoRChange }
|
||||
};
|
||||
MicroOp irq_mode1_program[] = {
|
||||
{ MicroOp::BeginIRQ },
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {BusOperation::Interrupt, 7, nullptr, &operation_}},
|
||||
{ MicroOp::BusOperation, nullptr, nullptr, {MachineCycle::Operation::Interrupt, 7, nullptr, &operation_}},
|
||||
PUSH(pc_),
|
||||
{ MicroOp::Move16, &temp16_.full, &pc_.full },
|
||||
{ MicroOp::MoveToNextProgram }
|
||||
};
|
||||
MicroOp irq_mode2_program[] = {
|
||||
{ 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_),
|
||||
{ MicroOp::Move8, &ir_.bytes.high, &temp16_.bytes.high },
|
||||
FETCH16L(pc_, temp16_),
|
||||
@ -781,7 +779,7 @@ template <class T> class Processor {
|
||||
while(1) {
|
||||
|
||||
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;
|
||||
if(!number_of_cycles_) {
|
||||
static_cast<T *>(this)->flush();
|
||||
|
@ -20,30 +20,30 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor<Concrete
|
||||
completed_cycles += cycle.length;
|
||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
switch(cycle.operation) {
|
||||
case BusOperation::ReadOpcode:
|
||||
case MachineCycle::Operation::ReadOpcode:
|
||||
// printf("! ");
|
||||
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));
|
||||
*cycle.value = memory_[address];
|
||||
break;
|
||||
case BusOperation::Write:
|
||||
case MachineCycle::Operation::Write:
|
||||
// printf("w %04x\n", address);
|
||||
memory_[address] = *cycle.value;
|
||||
break;
|
||||
|
||||
case BusOperation::Output:
|
||||
case MachineCycle::Operation::Output:
|
||||
break;
|
||||
case BusOperation::Input:
|
||||
case MachineCycle::Operation::Input:
|
||||
// This logic is selected specifically because it seems to match
|
||||
// the FUSE unit tests. It might need factoring out.
|
||||
*cycle.value = address >> 8;
|
||||
break;
|
||||
|
||||
case BusOperation::Internal:
|
||||
case MachineCycle::Operation::Internal:
|
||||
break;
|
||||
|
||||
case BusOperation::Interrupt:
|
||||
case MachineCycle::Operation::Interrupt:
|
||||
// A pick that means LD HL, (nn) if interpreted as an instruction but is otherwise
|
||||
// arbitrary.
|
||||
*cycle.value = 0x21;
|
||||
|
@ -22,7 +22,7 @@ class AllRAMProcessor:
|
||||
static AllRAMProcessor *Processor();
|
||||
|
||||
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) {
|
||||
delegate_ = delegate;
|
||||
|
Loading…
Reference in New Issue
Block a user