Added debugging and shift instructions to Z80

This commit is contained in:
transistor 2021-11-06 21:18:45 -07:00
parent 3da58c8d17
commit 2c6a1a1b3a
4 changed files with 124 additions and 67 deletions

61
src/cpus/z80/debugger.rs Normal file
View File

@ -0,0 +1,61 @@
use crate::error::Error;
use crate::system::System;
use crate::devices::{Address, Addressable, Debuggable};
use super::state::Z80;
use super::decode::Z80Decoder;
pub struct Z80Debugger {
pub breakpoints: Vec<u16>,
}
impl Z80Debugger {
pub fn new() -> Self {
Self {
breakpoints: vec!(),
}
}
}
impl Debuggable for Z80 {
fn add_breakpoint(&mut self, addr: Address) {
self.debugger.breakpoints.push(addr as u16);
}
fn remove_breakpoint(&mut self, addr: Address) {
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == addr as u16) {
self.debugger.breakpoints.remove(index);
}
}
fn print_current_step(&mut self, system: &System) -> Result<(), Error> {
self.decoder.decode_at(&mut self.port, self.state.pc)?;
self.decoder.dump_decoded(&mut self.port);
self.dump_state(system);
Ok(())
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
let mut decoder = Z80Decoder::new();
//decoder.dump_disassembly(&mut self.port, self.state.pc, 0x1000);
}
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
Ok(false)
}
}
impl Z80 {
pub fn check_breakpoints(&mut self, system: &System) {
for breakpoint in &self.debugger.breakpoints {
if *breakpoint == self.state.pc {
println!("Breakpoint reached: {:08x}", *breakpoint);
system.enable_debugging();
break;
}
}
}
}

View File

@ -7,6 +7,9 @@ use super::decode::{Condition, Instruction, LoadTarget, Target, OptionalSource,
use super::state::{Z80, Status, Flags, Register};
const DEV_NAME: &'static str = "z80-cpu";
enum RotateType {
Bit8,
Bit9,
@ -20,40 +23,12 @@ impl Steppable for Z80 {
}
fn on_error(&mut self, system: &System) {
//self.dump_state(system);
self.dump_state(system);
}
}
impl Interruptable for Z80 { }
impl Debuggable for Z80 {
fn add_breakpoint(&mut self, addr: Address) {
//self.debugger.breakpoints.push(addr as u32);
}
fn remove_breakpoint(&mut self, addr: Address) {
//if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == addr as u32) {
// self.debugger.breakpoints.remove(index);
//}
}
fn print_current_step(&mut self, system: &System) -> Result<(), Error> {
//self.decoder.decode_at(&mut self.port, self.state.pc)?;
//self.decoder.dump_decoded(&mut self.port);
self.dump_state(system);
Ok(())
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
//let mut decoder = M68kDecoder::new(self.cputype, 0);
//decoder.dump_disassembly(&mut self.port, self.state.pc, 0x1000);
}
fn execute_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {
Ok(false)
}
}
impl Transmutable for Z80 {
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
@ -112,13 +87,14 @@ impl Z80 {
}
pub fn decode_next(&mut self, system: &System) -> Result<(), Error> {
//self.check_breakpoints(system);
self.check_breakpoints(system);
//self.timer.decode.start();
self.decoder.decode_at(&mut self.port, self.state.pc)?;
//self.timer.decode.end();
//if self.debugger.use_tracing {
//self.decoder.dump_decoded(&mut self.port);
//self.dump_state(system);
//}
@ -350,7 +326,7 @@ impl Z80 {
//},
Instruction::OUTx(port) => {
// TODO this needs to be fixed
println!("OUT: {:x}", self.state.reg[Register::A as usize]);
println!("OUT ({:x}), {:x}", port, self.state.reg[Register::A as usize]);
},
Instruction::POP(regpair) => {
let value = self.pop_word()?;
@ -379,52 +355,52 @@ impl Z80 {
},
Instruction::RL(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let result = self.rotate_left(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_left(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::RLA => {
let value = self.get_register_value(Register::A);
let result = self.rotate_left(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_left(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_register_value(Register::A, result);
},
Instruction::RLC(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let result = self.rotate_left(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_left(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::RLCA => {
let value = self.get_register_value(Register::A);
let result = self.rotate_left(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_left(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_register_value(Register::A, result);
},
//Instruction::RLD => {
//},
Instruction::RR(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let result = self.rotate_right(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_right(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::RRA => {
let value = self.get_register_value(Register::A);
let result = self.rotate_right(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_right(value, RotateType::Bit9);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_register_value(Register::A, result);
},
Instruction::RRC(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let result = self.rotate_right(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_right(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::RRCA => {
let value = self.get_register_value(Register::A);
let result = self.rotate_right(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, false);
let (result, out_bit) = self.rotate_right(value, RotateType::Bit8);
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_register_value(Register::A, result);
},
//Instruction::RRD => {
@ -457,14 +433,35 @@ impl Z80 {
value = value | (1 << bit);
self.set_target_value(target, value);
},
//Instruction::SLA(target, opt_src) => {
//},
//Instruction::SLL(target, opt_src) => {
//},
//Instruction::SRA(target, opt_src) => {
//},
//Instruction::SRL(target, opt_src) => {
//},
Instruction::SLA(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let out_bit = get_msb(value as u16, Size::Byte);
let result = (value << 1) | 0x01;
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::SLL(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let out_bit = get_msb(value as u16, Size::Byte);
let result = value << 1;
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::SRA(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let out_bit = (value & 0x01) != 0;
let msb_mask = if get_msb(value as u16, Size::Byte) { 0x80 } else { 0 };
let result = (value >> 1) | msb_mask;
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::SRL(target, opt_src) => {
let value = self.get_opt_src_target_value(opt_src, target)?;
let out_bit = (value & 0x01) != 0;
let result = value >> 1;
self.set_logic_op_flags(result as u16, Size::Byte, out_bit);
self.set_target_value(target, result)?;
},
Instruction::SUB(target) => {
let src = self.get_target_value(target)?;
let acc = self.get_register_value(Register::A);
@ -480,14 +477,14 @@ impl Z80 {
self.set_logic_op_flags(result as u16, Size::Byte, false);
},
_ => {
panic!("unimplemented");
return Err(Error::new(&format!("{}: unimplemented instruction: {:?}", DEV_NAME, self.decoder.instruction)));
}
}
Ok(())
}
fn rotate_left(&mut self, mut value: u8, rtype: RotateType) -> u8 {
fn rotate_left(&mut self, mut value: u8, rtype: RotateType) -> (u8, bool) {
let out_bit = get_msb(value as u16, Size::Byte);
let in_bit = match rtype {
@ -497,11 +494,10 @@ impl Z80 {
value <<= 1;
value |= in_bit as u8;
self.set_flag(Flags::Carry, out_bit);
value
(value, out_bit)
}
fn rotate_right(&mut self, mut value: u8, rtype: RotateType) -> u8 {
fn rotate_right(&mut self, mut value: u8, rtype: RotateType) -> (u8, bool) {
let out_bit = (value & 0x01) != 0;
let in_bit = match rtype {
@ -511,8 +507,7 @@ impl Z80 {
value >>= 1;
value |= if in_bit { 0x80 } else { 0 };
self.set_flag(Flags::Carry, out_bit);
value
(value, out_bit)
}
fn push_word(&mut self, value: u16) -> Result<(), Error> {

View File

@ -2,6 +2,7 @@
pub mod state;
pub mod decode;
pub mod execute;
pub mod debugger;
pub use self::state::{Z80, Z80Type};

View File

@ -4,7 +4,7 @@ use crate::devices::Address;
use crate::memory::BusPort;
use super::decode::Z80Decoder;
//use super::debugger::M68kDebugger;
use super::debugger::Z80Debugger;
#[allow(dead_code)]
@ -89,7 +89,7 @@ pub struct Z80 {
pub frequency: u32,
pub state: Z80State,
pub decoder: Z80Decoder,
//pub debugger: M68kDebugger,
pub debugger: Z80Debugger,
pub port: BusPort,
}
@ -100,7 +100,7 @@ impl Z80 {
frequency,
state: Z80State::new(),
decoder: Z80Decoder::new(),
//debugger: M68kDebugger::new(),
debugger: Z80Debugger::new(),
port: port,
}
}
@ -108,8 +108,8 @@ impl Z80 {
#[allow(dead_code)]
pub fn reset(&mut self) {
self.state = Z80State::new();
//self.decoder = M68kDecoder::new(self.cputype, 0);
//self.debugger = M68kDebugger::new();
self.decoder = Z80Decoder::new();
self.debugger = Z80Debugger::new();
}
pub fn dump_state(&mut self, system: &System) {