1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! A Z80 and Z80N CPU core, stepped one clock edge at a time.
//!
//! The core is a hardware model, not an interpreter. A combinational microcode decode and ALU feed
//! a machine-cycle and T-state sequencer, and register writes commit on the clock edge.
//!
//! [`Cpu::tick`] advances one edge — half a T-state. That makes each bus transition a real Z80
//! presents visible on its own tick: the address becoming valid, the control lines asserting, the
//! data bus being latched.
//!
//! [`Cpu::step`] runs to the next instruction boundary and returns the T-states taken, for callers
//! that don't need that detail.
//!
//! # Driving the core
//!
//! Everything outside the CPU — memory, ports, wait states, the interrupt vector — comes through
//! the [`Host`] trait, which the caller implements:
//!
//! ```
//! use hg80::{Cpu, Host};
//!
//! struct FlatMemory {
//! bytes: [u8; 0x10000],
//! }
//!
//! impl Host for FlatMemory {
//! fn read(&mut self, address: u16, _at: u32) -> u8 {
//! self.bytes[address as usize]
//! }
//!
//! fn write(&mut self, address: u16, value: u8, _at: u32) {
//! self.bytes[address as usize] = value;
//! }
//!
//! fn input(&mut self, _port: u16, _at: u32) -> u8 {
//! 0xFF
//! }
//!
//! fn output(&mut self, _port: u16, _value: u8, _at: u32) {}
//! }
//!
//! let mut cpu = Cpu::new();
//! let mut host = FlatMemory { bytes: [0; 0x10000] };
//! cpu.reset();
//! assert_eq!(cpu.registers().pc, 0);
//! ```
//!
//! # Z80 and Z80N
//!
//! [`Cpu::set_z80n_enabled`] switches between a plain Z80 and the Z80N superset at run time. With
//! Z80N off, the extended `ED`-prefixed opcodes decode as the no-operation forms a real Z80 gives
//! them, so one instance can model either part.
//!
//! Z80N instructions with effects outside the CPU don't reach outside the core themselves. They're
//! reported to the host as a [`Z80nCommand`] carrying its operand, and the host does the work. That
//! keeps the core free of any particular machine's memory-management or register-file details.
extern crate std;
pub use flag;
pub use Cpu;
pub use ;
pub use ;