mirror of
https://github.com/transistorfet/moa.git
synced 2025-02-16 11:30:33 +00:00
Added debugging and shift instructions to Z80
This commit is contained in:
parent
3da58c8d17
commit
2c6a1a1b3a
61
src/cpus/z80/debugger.rs
Normal file
61
src/cpus/z80/debugger.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -2,6 +2,7 @@
|
||||
pub mod state;
|
||||
pub mod decode;
|
||||
pub mod execute;
|
||||
pub mod debugger;
|
||||
|
||||
pub use self::state::{Z80, Z80Type};
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user