2023-06-11 03:28:40 +00:00
|
|
|
use std::rc::Rc;
|
|
|
|
use std::cell::RefCell;
|
2024-02-24 21:02:09 +00:00
|
|
|
use femtos::{Instant, Frequency};
|
2024-04-07 17:38:41 +00:00
|
|
|
use emulator_hal::{Instant as EmuInstant, BusAccess};
|
2023-06-11 03:28:40 +00:00
|
|
|
|
2024-03-02 05:17:09 +00:00
|
|
|
use moa_core::{Address, Bus, BusPort};
|
|
|
|
use moa_signals::Signal;
|
2021-11-02 05:06:40 +00:00
|
|
|
|
2022-09-25 06:14:03 +00:00
|
|
|
use crate::debugger::Z80Debugger;
|
2024-04-01 04:17:54 +00:00
|
|
|
use crate::execute::Z80Cycle;
|
2024-03-02 18:57:16 +00:00
|
|
|
use crate::instructions::{Instruction, Register, InterruptMode};
|
2021-11-02 05:06:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
pub enum Z80Type {
|
|
|
|
Z80,
|
|
|
|
}
|
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2021-11-02 05:06:40 +00:00
|
|
|
pub enum Status {
|
|
|
|
Init,
|
|
|
|
Running,
|
|
|
|
Halted,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(u8)]
|
|
|
|
#[allow(dead_code)]
|
2023-03-06 04:19:49 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2024-03-17 18:03:52 +00:00
|
|
|
#[rustfmt::skip]
|
2021-11-02 05:06:40 +00:00
|
|
|
pub enum Flags {
|
2021-11-03 03:58:03 +00:00
|
|
|
Carry = 0x01,
|
|
|
|
AddSubtract = 0x02,
|
|
|
|
Parity = 0x04,
|
2021-11-11 00:05:16 +00:00
|
|
|
F3 = 0x08,
|
2021-11-03 03:58:03 +00:00
|
|
|
HalfCarry = 0x10,
|
2021-11-11 00:05:16 +00:00
|
|
|
F5 = 0x20,
|
2021-11-03 03:58:03 +00:00
|
|
|
Zero = 0x40,
|
|
|
|
Sign = 0x80,
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
2021-11-02 05:06:40 +00:00
|
|
|
pub struct Z80State {
|
|
|
|
pub status: Status,
|
|
|
|
|
|
|
|
pub pc: u16,
|
|
|
|
pub sp: u16,
|
|
|
|
pub ix: u16,
|
|
|
|
pub iy: u16,
|
|
|
|
|
|
|
|
pub reg: [u8; 8],
|
2021-11-05 04:30:33 +00:00
|
|
|
pub shadow_reg: [u8; 8],
|
2021-11-02 05:06:40 +00:00
|
|
|
|
|
|
|
pub i: u8,
|
|
|
|
pub r: u8,
|
2023-05-14 02:41:20 +00:00
|
|
|
|
|
|
|
pub iff1: bool,
|
|
|
|
pub iff2: bool,
|
|
|
|
pub im: InterruptMode,
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
impl Default for Z80State {
|
|
|
|
fn default() -> Self {
|
2021-11-02 05:06:40 +00:00
|
|
|
Self {
|
|
|
|
status: Status::Init,
|
|
|
|
|
|
|
|
pc: 0,
|
|
|
|
sp: 0,
|
|
|
|
ix: 0,
|
|
|
|
iy: 0,
|
|
|
|
|
|
|
|
reg: [0; 8],
|
2021-11-05 04:30:33 +00:00
|
|
|
shadow_reg: [0; 8],
|
2021-11-02 05:06:40 +00:00
|
|
|
|
|
|
|
i: 0,
|
|
|
|
r: 0,
|
2023-05-14 02:41:20 +00:00
|
|
|
|
|
|
|
iff1: false,
|
|
|
|
iff2: false,
|
|
|
|
im: InterruptMode::Mode0,
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
}
|
2023-03-06 04:19:49 +00:00
|
|
|
}
|
2021-11-09 19:03:57 +00:00
|
|
|
|
2023-03-06 04:19:49 +00:00
|
|
|
impl Z80State {
|
2021-11-09 19:03:57 +00:00
|
|
|
pub fn get_register(&mut self, reg: Register) -> u8 {
|
|
|
|
self.reg[reg as usize]
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_register(&mut self, reg: Register, value: u8) {
|
|
|
|
self.reg[reg as usize] = value;
|
|
|
|
}
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
|
2024-04-07 17:38:41 +00:00
|
|
|
#[derive(Clone, Debug, Default)]
|
|
|
|
pub struct Z80Signals {
|
|
|
|
pub reset: bool,
|
|
|
|
pub bus_request: bool,
|
|
|
|
}
|
|
|
|
|
2024-03-02 18:57:16 +00:00
|
|
|
#[derive(Clone, Debug, thiserror::Error)]
|
2024-03-03 07:48:19 +00:00
|
|
|
pub enum Z80Error /* <B: fmt::Display> */ {
|
2024-03-02 18:57:16 +00:00
|
|
|
#[error("cpu halted")]
|
|
|
|
Halted,
|
|
|
|
#[error("breakpoint reached")]
|
|
|
|
Breakpoint,
|
|
|
|
#[error("unimplemented instruction {0:?}")]
|
|
|
|
Unimplemented(Instruction),
|
|
|
|
#[error("bus error: {0}")]
|
2024-03-03 07:48:19 +00:00
|
|
|
BusError(String /* B */),
|
2024-03-02 18:57:16 +00:00
|
|
|
}
|
|
|
|
|
2024-04-01 04:17:54 +00:00
|
|
|
|
|
|
|
pub type Z80Address = u16;
|
|
|
|
pub type Z80IOAddress = u16;
|
|
|
|
|
|
|
|
pub enum Z80AddressSpace {
|
|
|
|
Memory(Z80Address),
|
|
|
|
IO(Z80IOAddress),
|
|
|
|
}
|
|
|
|
|
2023-05-10 04:50:42 +00:00
|
|
|
#[derive(Clone)]
|
2024-04-01 04:17:54 +00:00
|
|
|
pub struct Z80<Instant> {
|
2021-11-02 05:06:40 +00:00
|
|
|
pub cputype: Z80Type,
|
2023-04-23 22:46:47 +00:00
|
|
|
pub frequency: Frequency,
|
2021-11-02 05:06:40 +00:00
|
|
|
pub state: Z80State,
|
2021-11-07 04:18:45 +00:00
|
|
|
pub debugger: Z80Debugger,
|
2024-04-01 04:17:54 +00:00
|
|
|
pub previous_cycle: Z80Cycle<Instant>,
|
2024-04-07 17:38:41 +00:00
|
|
|
pub signals: Z80Signals,
|
2024-04-01 04:17:54 +00:00
|
|
|
// TODO activate later
|
|
|
|
//pub reset: Signal<bool>,
|
|
|
|
//pub bus_request: Signal<bool>,
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
|
2024-04-01 04:17:54 +00:00
|
|
|
impl<Instant> Z80<Instant>
|
|
|
|
where
|
|
|
|
Instant: EmuInstant,
|
|
|
|
{
|
2024-04-07 17:38:41 +00:00
|
|
|
pub fn new(cputype: Z80Type, frequency: Frequency) -> Self {
|
2021-11-02 05:06:40 +00:00
|
|
|
Self {
|
|
|
|
cputype,
|
|
|
|
frequency,
|
2023-03-06 04:19:49 +00:00
|
|
|
state: Z80State::default(),
|
|
|
|
debugger: Z80Debugger::default(),
|
2024-04-01 04:17:54 +00:00
|
|
|
previous_cycle: Z80Cycle::at_time(Instant::START),
|
2024-04-07 17:38:41 +00:00
|
|
|
signals: Z80Signals::default(),
|
2024-04-01 04:17:54 +00:00
|
|
|
//reset: Signal::new(false),
|
|
|
|
//bus_request: Signal::new(false),
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-07 17:38:41 +00:00
|
|
|
pub fn from_type(cputype: Z80Type, frequency: Frequency) -> Self {
|
2023-06-11 03:28:40 +00:00
|
|
|
match cputype {
|
2024-04-07 17:38:41 +00:00
|
|
|
Z80Type::Z80 => Self::new(cputype, frequency),
|
2023-06-11 03:28:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-02 05:06:40 +00:00
|
|
|
#[allow(dead_code)]
|
2021-12-13 19:05:22 +00:00
|
|
|
pub fn clear_state(&mut self) {
|
2023-03-06 04:19:49 +00:00
|
|
|
self.state = Z80State::default();
|
|
|
|
self.debugger = Z80Debugger::default();
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
|
2024-04-07 17:38:41 +00:00
|
|
|
pub fn dump_state<Bus>(&mut self, clock: Instant, bus: &mut Bus)
|
|
|
|
where
|
|
|
|
Bus: BusAccess<Z80Address, Instant = Instant>,
|
|
|
|
{
|
2021-11-02 05:06:40 +00:00
|
|
|
println!("Status: {:?}", self.state.status);
|
2021-11-05 04:30:33 +00:00
|
|
|
println!("PC: {:#06x}", self.state.pc);
|
|
|
|
println!("SP: {:#06x}", self.state.sp);
|
|
|
|
println!("IX: {:#06x}", self.state.ix);
|
|
|
|
println!("IY: {:#06x}", self.state.iy);
|
|
|
|
|
2024-03-17 18:03:52 +00:00
|
|
|
println!(
|
|
|
|
"A: {:#04x} F: {:#04x} A': {:#04x} F': {:#04x}",
|
|
|
|
self.state.reg[Register::A as usize],
|
|
|
|
self.state.reg[Register::F as usize],
|
|
|
|
self.state.shadow_reg[Register::A as usize],
|
|
|
|
self.state.shadow_reg[Register::F as usize]
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"B: {:#04x} C: {:#04x} B': {:#04x} C': {:#04x}",
|
|
|
|
self.state.reg[Register::B as usize],
|
|
|
|
self.state.reg[Register::C as usize],
|
|
|
|
self.state.shadow_reg[Register::B as usize],
|
|
|
|
self.state.shadow_reg[Register::C as usize]
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"D: {:#04x} E: {:#04x} D': {:#04x} E': {:#04x}",
|
|
|
|
self.state.reg[Register::D as usize],
|
|
|
|
self.state.reg[Register::E as usize],
|
|
|
|
self.state.shadow_reg[Register::D as usize],
|
|
|
|
self.state.shadow_reg[Register::E as usize]
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"H: {:#04x} L: {:#04x} H': {:#04x} L': {:#04x}",
|
|
|
|
self.state.reg[Register::H as usize],
|
|
|
|
self.state.reg[Register::L as usize],
|
|
|
|
self.state.shadow_reg[Register::H as usize],
|
|
|
|
self.state.shadow_reg[Register::L as usize]
|
|
|
|
);
|
2021-11-02 05:06:40 +00:00
|
|
|
|
2023-05-14 02:41:20 +00:00
|
|
|
println!("I: {:#04x} R: {:#04x}", self.state.i, self.state.r);
|
|
|
|
println!("IM: {:?} IFF1: {:?} IFF2: {:?}", self.state.im, self.state.iff1, self.state.iff2);
|
|
|
|
|
2024-04-07 17:38:41 +00:00
|
|
|
println!(
|
|
|
|
"Current Instruction: {} {:?}",
|
|
|
|
self.previous_cycle.decoder.format_instruction_bytes(bus),
|
|
|
|
self.previous_cycle.decoder.instruction
|
|
|
|
);
|
2024-04-01 04:17:54 +00:00
|
|
|
println!("Previous Instruction: {:?}", self.previous_cycle.decoder.instruction);
|
2023-03-06 04:19:49 +00:00
|
|
|
println!();
|
2024-04-01 04:17:54 +00:00
|
|
|
// TODO disabled until function is reimplemented
|
|
|
|
//self.port.dump_memory(clock, self.state.sp as Address, 0x40);
|
2023-03-06 04:19:49 +00:00
|
|
|
println!();
|
2021-11-02 05:06:40 +00:00
|
|
|
}
|
|
|
|
}
|