From f205e231b62d62c72186c1d9f5277e2bce693380 Mon Sep 17 00:00:00 2001 From: transistor Date: Sun, 14 May 2023 21:12:38 -0700 Subject: [PATCH] Fixed tests failing due to wrapping into past the end of memory --- emulator/core/src/error.rs | 43 ++++++++++++--- emulator/core/src/memory.rs | 28 ++++++---- emulator/cpus/m68k/src/execute.rs | 92 ------------------------------- emulator/cpus/z80/src/execute.rs | 19 +++---- tests/rad_tests/latest.txt | 8 +-- tests/rad_tests/src/main.rs | 33 ++++++----- todo.txt | 3 + 7 files changed, 86 insertions(+), 140 deletions(-) diff --git a/emulator/core/src/error.rs b/emulator/core/src/error.rs index d8db8c1..1666f4e 100644 --- a/emulator/core/src/error.rs +++ b/emulator/core/src/error.rs @@ -2,11 +2,18 @@ #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ErrorType { Assertion, - Emulator, + Emulator(EmulatorErrorKind), Processor, Breakpoint, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum EmulatorErrorKind { + Misc, + MemoryAlignment, +} + + #[derive(Debug)] pub struct Error { pub err: ErrorType, @@ -15,11 +22,25 @@ pub struct Error { } impl Error { - pub fn new(msg: &str) -> Error { + pub fn new(msg: S) -> Error + where + S: Into, + { Error { - err: ErrorType::Emulator, + err: ErrorType::Emulator(EmulatorErrorKind::Misc), native: 0, - msg: msg.to_string(), + msg: msg.into(), + } + } + + pub fn emulator(kind: EmulatorErrorKind, msg: S) -> Error + where + S: Into, + { + Error { + err: ErrorType::Emulator(kind), + native: 0, + msg: msg.into(), } } @@ -31,19 +52,25 @@ impl Error { } } - pub fn breakpoint(msg: &str) -> Error { + pub fn breakpoint(msg: S) -> Error + where + S: Into, + { Error { err: ErrorType::Breakpoint, native: 0, - msg: msg.to_string(), + msg: msg.into(), } } - pub fn assertion(msg: &str) -> Error { + pub fn assertion(msg: S) -> Error + where + S: Into, + { Error { err: ErrorType::Assertion, native: 0, - msg: msg.to_string(), + msg: msg.into(), } } } diff --git a/emulator/core/src/memory.rs b/emulator/core/src/memory.rs index 47e092a..ccd3d91 100644 --- a/emulator/core/src/memory.rs +++ b/emulator/core/src/memory.rs @@ -1,11 +1,12 @@ use std::fs; +use std::cmp; use std::rc::Rc; use std::cell::RefCell; use std::fmt::Write; use crate::info; -use crate::error::Error; +use crate::error::{Error, EmulatorErrorKind}; use crate::clock::ClockTime; use crate::devices::{Address, Addressable, Transmutable, TransmutableBox, read_beu16}; @@ -274,20 +275,17 @@ pub struct BusPort { offset: Address, address_mask: Address, data_width: u8, + error_on_alignment: bool, subdevice: Rc>, } impl BusPort { pub fn new(offset: Address, address_bits: u8, data_bits: u8, bus: Rc>) -> Self { - let mut address_mask = 0; - for _ in 0..address_bits { - address_mask = (address_mask << 1) | 0x01; - } - Self { offset, - address_mask, + address_mask: (1 << address_bits) - 1, data_width: data_bits / 8, + error_on_alignment: false, subdevice: bus, } } @@ -311,21 +309,31 @@ impl Addressable for BusPort { } fn read(&mut self, clock: ClockTime, addr: Address, data: &mut [u8]) -> Result<(), Error> { + if self.error_on_alignment && addr % self.data_width as Address != 0 { + return Err(Error::emulator(EmulatorErrorKind::MemoryAlignment, format!("misaligned memory access at {:x}", addr))); + } + let addr = self.offset + (addr & self.address_mask); let mut subdevice = self.subdevice.borrow_mut(); for i in (0..data.len()).step_by(self.data_width as usize) { - let end = std::cmp::min(i + self.data_width as usize, data.len()); - subdevice.read(clock, addr + i as Address, &mut data[i..end])?; + let addr_index = (addr + i as Address) & self.address_mask; + let end = cmp::min(i + self.data_width as usize, data.len()); + subdevice.read(clock, addr_index, &mut data[i..end])?; } Ok(()) } fn write(&mut self, clock: ClockTime, addr: Address, data: &[u8]) -> Result<(), Error> { + if self.error_on_alignment && addr % self.data_width as Address != 0 { + return Err(Error::emulator(EmulatorErrorKind::MemoryAlignment, format!("misaligned memory access at {:x}", addr))); + } + let addr = self.offset + (addr & self.address_mask); let mut subdevice = self.subdevice.borrow_mut(); for i in (0..data.len()).step_by(self.data_width as usize) { + let addr_index = (addr + i as Address) & self.address_mask; let end = std::cmp::min(i + self.data_width as usize, data.len()); - subdevice.write(clock, addr + i as Address, &data[i..end])?; + subdevice.write(clock, addr_index, &data[i..end])?; } Ok(()) } diff --git a/emulator/cpus/m68k/src/execute.rs b/emulator/cpus/m68k/src/execute.rs index 172bfae..358c71a 100644 --- a/emulator/cpus/m68k/src/execute.rs +++ b/emulator/cpus/m68k/src/execute.rs @@ -305,7 +305,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_abcd(&mut self, src: Target, dest: Target) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Byte, Used::Once)?; let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?; @@ -330,7 +329,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_add(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -342,7 +340,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_adda(&mut self, src: Target, dest: Register, size: Size) -> Result<(), Error> { let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32; let dest_val = *self.get_a_reg_mut(dest); @@ -351,7 +348,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_addx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -373,7 +369,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_and(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -383,20 +378,17 @@ impl M68k { Ok(()) } - #[inline] fn execute_and_to_ccr(&mut self, value: u8) -> Result<(), Error> { self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) & (value as u16)); Ok(()) } - #[inline] fn execute_and_to_sr(&mut self, value: u16) -> Result<(), Error> { self.require_supervisor()?; self.set_sr(self.state.sr & value); Ok(()) } - #[inline] fn execute_asd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> { let count = self.get_target_value(count, size, Used::Once)? % 64; let value = self.get_target_value(target, size, Used::Twice)?; @@ -430,7 +422,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), Error> { let should_branch = self.get_current_condition(cond); if should_branch { @@ -442,7 +433,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bra(&mut self, offset: i32) -> Result<(), Error> { if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) { self.state.pc -= 2; @@ -451,7 +441,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bsr(&mut self, offset: i32) -> Result<(), Error> { self.push_long(self.state.pc)?; let sp = *self.get_stack_pointer_mut(); @@ -463,7 +452,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bchg(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> { let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?; let mut src_val = self.get_target_value(target, size, Used::Twice)?; @@ -473,7 +461,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bclr(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> { let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?; let mut src_val = self.get_target_value(target, size, Used::Twice)?; @@ -483,7 +470,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bset(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> { let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?; let mut value = self.get_target_value(target, size, Used::Twice)?; @@ -493,7 +479,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_btst(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> { let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?; let value = self.get_target_value(target, size, Used::Once)?; @@ -501,7 +486,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bfchg(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -512,7 +496,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bfclr(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -523,7 +506,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bfexts(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -540,7 +522,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bfextu(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -551,7 +532,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bfset(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -562,7 +542,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_bftst(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> { let (offset, width) = self.get_bit_field_args(offset, width); let mask = get_bit_field_mask(offset, width); @@ -572,7 +551,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_chk(&mut self, target: Target, reg: Register, size: Size) -> Result<(), Error> { let upper_bound = sign_extend_to_long(self.get_target_value(target, size, Used::Once)?, size); let dreg = sign_extend_to_long(self.state.d_reg[reg as usize], size); @@ -589,7 +567,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), Error> { if self.cputype == M68kType::MC68000 { self.get_target_value(target, size, Used::Twice)?; @@ -602,7 +579,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_cmp(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Once)?; @@ -612,7 +588,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_cmpa(&mut self, src: Target, reg: Register, size: Size) -> Result<(), Error> { let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32; let dest_val = *self.get_a_reg_mut(reg); @@ -622,7 +597,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_dbcc(&mut self, cond: Condition, reg: Register, offset: i16) -> Result<(), Error> { let condition_true = self.get_current_condition(cond); if !condition_true { @@ -638,7 +612,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_divw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Word, Used::Once)?; if src_val == 0 { @@ -679,7 +652,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_divl(&mut self, src: Target, dest_h: Option, dest_l: Register, sign: Sign) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Long, Used::Once)?; if src_val == 0 { @@ -713,7 +685,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_eor(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -723,20 +694,17 @@ impl M68k { Ok(()) } - #[inline] fn execute_eor_to_ccr(&mut self, value: u8) -> Result<(), Error> { self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16))); Ok(()) } - #[inline] fn execute_eor_to_sr(&mut self, value: u16) -> Result<(), Error> { self.require_supervisor()?; self.set_sr(self.state.sr ^ value); Ok(()) } - #[inline] fn execute_exg(&mut self, target1: Target, target2: Target) -> Result<(), Error> { let value1 = self.get_target_value(target1, Size::Long, Used::Twice)?; let value2 = self.get_target_value(target2, Size::Long, Used::Twice)?; @@ -745,7 +713,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_ext(&mut self, reg: Register, from_size: Size, to_size: Size) -> Result<(), Error> { let input = get_value_sized(self.state.d_reg[reg as usize], from_size); let result = match (from_size, to_size) { @@ -759,13 +726,11 @@ impl M68k { Ok(()) } - #[inline] fn execute_illegal(&mut self) -> Result<(), Error> { self.exception(Exceptions::IllegalInstruction as u8, false)?; Ok(()) } - #[inline] fn execute_jmp(&mut self, target: Target) -> Result<(), Error> { let addr = self.get_target_address(target)?; if let Err(err) = self.set_pc(addr) { @@ -775,7 +740,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_jsr(&mut self, target: Target) -> Result<(), Error> { let previous_pc = self.state.pc; let addr = self.get_target_address(target)?; @@ -791,7 +755,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_lea(&mut self, target: Target, reg: Register) -> Result<(), Error> { let value = self.get_target_address(target)?; let addr = self.get_a_reg_mut(reg); @@ -799,7 +762,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_link(&mut self, reg: Register, offset: i32) -> Result<(), Error> { *self.get_stack_pointer_mut() -= 4; let sp = *self.get_stack_pointer_mut(); @@ -810,7 +772,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_lsd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> { let count = self.get_target_value(count, size, Used::Once)? % 64; let mut pair = (self.get_target_value(target, size, Used::Twice)?, false); @@ -831,7 +792,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; self.set_logic_flags(src_val, size); @@ -839,7 +799,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_movea(&mut self, src: Target, reg: Register, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let src_val = sign_extend_to_long(src_val, size) as u32; @@ -848,14 +807,12 @@ impl M68k { Ok(()) } - #[inline] fn execute_move_from_sr(&mut self, target: Target) -> Result<(), Error> { self.require_supervisor()?; self.set_target_value(target, self.state.sr as u32, Size::Word, Used::Once)?; Ok(()) } - #[inline] fn execute_move_to_sr(&mut self, target: Target) -> Result<(), Error> { self.require_supervisor()?; let value = self.get_target_value(target, Size::Word, Used::Once)? as u16; @@ -863,14 +820,12 @@ impl M68k { Ok(()) } - #[inline] fn execute_move_to_ccr(&mut self, target: Target) -> Result<(), Error> { let value = self.get_target_value(target, Size::Word, Used::Once)? as u16; self.set_sr((self.state.sr & 0xFF00) | (value & 0x00FF)); Ok(()) } - #[inline] fn execute_movec(&mut self, target: Target, control_reg: ControlRegister, dir: Direction) -> Result<(), Error> { self.require_supervisor()?; match dir { @@ -888,7 +843,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), Error> { let addr = self.get_target_address(target)?; @@ -936,7 +890,6 @@ impl M68k { Ok(()) } - #[inline] fn move_memory_to_registers(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result { for i in 0..8 { if (mask & 0x01) != 0 { @@ -955,7 +908,6 @@ impl M68k { Ok(addr) } - #[inline] fn move_registers_to_memory(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result { for i in 0..8 { if (mask & 0x01) != 0 { @@ -975,7 +927,6 @@ impl M68k { Ok(addr) } - #[inline] fn move_registers_to_memory_reverse(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result { for i in (0..8).rev() { if (mask & 0x01) != 0 { @@ -995,7 +946,6 @@ impl M68k { Ok(addr) } - #[inline] fn execute_movep(&mut self, dreg: Register, areg: Register, offset: i16, size: Size, dir: Direction) -> Result<(), Error> { match dir { Direction::ToTarget => { @@ -1022,7 +972,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_moveq(&mut self, data: u8, reg: Register) -> Result<(), Error> { let value = sign_extend_to_long(data as u32, Size::Byte) as u32; self.state.d_reg[reg as usize] = value; @@ -1030,7 +979,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_moveusp(&mut self, target: Target, dir: Direction) -> Result<(), Error> { self.require_supervisor()?; match dir { @@ -1040,7 +988,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_mulw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Word, Used::Once)?; let dest_val = get_value_sized(self.state.d_reg[dest as usize], Size::Word); @@ -1054,7 +1001,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_mull(&mut self, src: Target, dest_h: Option, dest_l: Register, sign: Sign) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Long, Used::Once)?; let dest_val = get_value_sized(self.state.d_reg[dest_l as usize], Size::Long); @@ -1071,7 +1017,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_nbcd(&mut self, dest: Target) -> Result<(), Error> { let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?; let result = self.execute_sbcd_val(dest_val, 0)?; @@ -1079,7 +1024,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_neg(&mut self, target: Target, size: Size) -> Result<(), Error> { let original = self.get_target_value(target, size, Used::Twice)?; let (result, overflow) = overflowing_sub_signed_sized(0, original, size); @@ -1090,7 +1034,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_negx(&mut self, dest: Target, size: Size) -> Result<(), Error> { let dest_val = self.get_target_value(dest, size, Used::Twice)?; let extend = self.get_flag(Flags::Extend) as u32; @@ -1111,7 +1054,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_not(&mut self, target: Target, size: Size) -> Result<(), Error> { let mut value = self.get_target_value(target, size, Used::Twice)?; value = get_value_sized(!value, size); @@ -1120,7 +1062,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_or(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -1130,34 +1071,29 @@ impl M68k { Ok(()) } - #[inline] fn execute_or_to_ccr(&mut self, value: u8) -> Result<(), Error> { self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) | (value as u16))); Ok(()) } - #[inline] fn execute_or_to_sr(&mut self, value: u16) -> Result<(), Error> { self.require_supervisor()?; self.set_sr(self.state.sr | value); Ok(()) } - #[inline] fn execute_pea(&mut self, target: Target) -> Result<(), Error> { let value = self.get_target_address(target)?; self.push_long(value)?; Ok(()) } - #[inline] fn execute_reset(&mut self) -> Result<(), Error> { self.require_supervisor()?; // TODO this only resets external devices and not internal ones Ok(()) } - #[inline] fn execute_rod(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> { let count = self.get_target_value(count, size, Used::Once)? % 64; let mut pair = (self.get_target_value(target, size, Used::Twice)?, false); @@ -1174,7 +1110,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_roxd(&mut self, count: Target, target: Target, size: Size, shift_dir: ShiftDirection) -> Result<(), Error> { let count = self.get_target_value(count, size, Used::Once)? % 64; let mut pair = (self.get_target_value(target, size, Used::Twice)?, false); @@ -1192,7 +1127,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_rte(&mut self) -> Result<(), Error> { self.require_supervisor()?; let sr = self.pop_word()?; @@ -1210,7 +1144,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_rtr(&mut self) -> Result<(), Error> { let ccr = self.pop_word()?; let addr = self.pop_long()?; @@ -1222,7 +1155,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_rts(&mut self) -> Result<(), Error> { self.debugger.stack_tracer.pop_return(); let addr = self.pop_long()?; @@ -1233,7 +1165,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_scc(&mut self, cond: Condition, target: Target) -> Result<(), Error> { let condition_true = self.get_current_condition(cond); if condition_true { @@ -1244,7 +1175,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_stop(&mut self, flags: u16) -> Result<(), Error> { self.require_supervisor()?; self.set_sr(flags); @@ -1252,7 +1182,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_sbcd(&mut self, src: Target, dest: Target) -> Result<(), Error> { let src_val = self.get_target_value(src, Size::Byte, Used::Once)?; let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?; @@ -1261,7 +1190,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_sbcd_val(&mut self, src_val: u32, dest_val: u32) -> Result { let extend_flag = self.get_flag(Flags::Extend) as u32; let src_parts = get_nibbles_from_byte(src_val); @@ -1283,7 +1211,6 @@ impl M68k { Ok(result) } - #[inline] fn execute_sub(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -1295,7 +1222,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_suba(&mut self, src: Target, dest: Register, size: Size) -> Result<(), Error> { let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32; let dest_val = *self.get_a_reg_mut(dest); @@ -1304,7 +1230,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_subx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> { let src_val = self.get_target_value(src, size, Used::Once)?; let dest_val = self.get_target_value(dest, size, Used::Twice)?; @@ -1326,7 +1251,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_swap(&mut self, reg: Register) -> Result<(), Error> { let value = self.state.d_reg[reg as usize]; self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16); @@ -1334,7 +1258,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_tas(&mut self, target: Target) -> Result<(), Error> { let value = self.get_target_value(target, Size::Byte, Used::Twice)?; self.set_flag(Flags::Negative, (value & 0x80) != 0); @@ -1345,20 +1268,17 @@ impl M68k { Ok(()) } - #[inline] fn execute_tst(&mut self, target: Target, size: Size) -> Result<(), Error> { let value = self.get_target_value(target, size, Used::Once)?; self.set_logic_flags(value, size); Ok(()) } - #[inline] fn execute_trap(&mut self, number: u8) -> Result<(), Error> { self.exception(32 + number, false)?; Ok(()) } - #[inline] fn execute_trapv(&mut self) -> Result<(), Error> { if self.get_flag(Flags::Overflow) { self.exception(Exceptions::TrapvInstruction as u8, false)?; @@ -1366,7 +1286,6 @@ impl M68k { Ok(()) } - #[inline] fn execute_unlk(&mut self, reg: Register) -> Result<(), Error> { let value = *self.get_a_reg_mut(reg); *self.get_stack_pointer_mut() = value; @@ -1376,14 +1295,12 @@ impl M68k { Ok(()) } - #[inline] fn execute_unimplemented_a(&mut self, _: u16) -> Result<(), Error> { self.state.pc -= 2; self.exception(Exceptions::LineAEmulator as u8, false)?; Ok(()) } - #[inline] fn execute_unimplemented_f(&mut self, _: u16) -> Result<(), Error> { self.state.pc -= 2; self.exception(Exceptions::LineFEmulator as u8, false)?; @@ -1658,12 +1575,10 @@ impl M68k { } } - #[inline(always)] fn get_stack_pointer_mut(&mut self) -> &mut u32 { if self.is_supervisor() { &mut self.state.ssp } else { &mut self.state.usp } } - #[inline(always)] fn get_a_reg(&self, reg: Register) -> u32 { if reg == 7 { if self.is_supervisor() { self.state.ssp } else { self.state.usp } @@ -1672,7 +1587,6 @@ impl M68k { } } - #[inline(always)] fn get_a_reg_mut(&mut self, reg: Register) -> &mut u32 { if reg == 7 { if self.is_supervisor() { &mut self.state.ssp } else { &mut self.state.usp } @@ -1681,12 +1595,10 @@ impl M68k { } } - #[inline(always)] fn is_supervisor(&self) -> bool { self.state.sr & (Flags:: Supervisor as u16) != 0 } - #[inline(always)] fn require_supervisor(&self) -> Result<(), Error> { if self.is_supervisor() { Ok(()) @@ -1700,12 +1612,10 @@ impl M68k { self.state.sr = value & mask; } - #[inline(always)] fn get_flag(&self, flag: Flags) -> bool { (self.state.sr & (flag as u16)) != 0 } - #[inline(always)] fn set_flag(&mut self, flag: Flags, value: bool) { self.state.sr = (self.state.sr & !(flag as u16)) | (if value { flag as u16 } else { 0 }); } @@ -1909,7 +1819,6 @@ fn get_sub_overflow(operand1: u32, operand2: u32, result: u32, size: Size) -> bo (msb1 && msb2 && !msb_res) || (!msb1 && !msb2 && msb_res) } -#[inline(always)] fn get_msb(value: u32, size: Size) -> bool { match size { Size::Byte => (value & 0x00000080) != 0, @@ -1918,7 +1827,6 @@ fn get_msb(value: u32, size: Size) -> bool { } } -#[inline(always)] fn get_msb_mask(value: u32, size: Size) -> u32 { match size { Size::Byte => value & 0x00000080, diff --git a/emulator/cpus/z80/src/execute.rs b/emulator/cpus/z80/src/execute.rs index b56d5e5..ff346a0 100644 --- a/emulator/cpus/z80/src/execute.rs +++ b/emulator/cpus/z80/src/execute.rs @@ -479,7 +479,7 @@ impl Z80 { fn execute_ini(&mut self) -> Result<(), Error> { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); - let value = self.get_ioport_value(b, c)?; + let value = self.read_ioport_value(b, c)?; self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), value as u16)?; let hl = self.get_register_pair_value(RegisterPair::HL).wrapping_add(1); @@ -495,7 +495,7 @@ impl Z80 { fn execute_inic(&mut self, reg: Register) -> Result<(), Error> { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); - let value = self.get_ioport_value(b, c)?; + let value = self.read_ioport_value(b, c)?; self.set_register_value(reg, value); self.set_numeric_flags(value as u16, Size::Byte); @@ -510,7 +510,7 @@ impl Z80 { fn execute_inx(&mut self, n: u8) -> Result<(), Error> { let a = self.get_register_value(Register::A); - let value = self.get_ioport_value(a, n)?; + let value = self.read_ioport_value(a, n)?; self.set_register_value(Register::A, value); Ok(()) } @@ -630,7 +630,7 @@ impl Z80 { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); let value = self.get_register_value(reg); - self.set_ioport_value(b, c, value)?; + self.write_ioport_value(b, c, value)?; Ok(()) } @@ -640,7 +640,7 @@ impl Z80 { fn execute_outx(&mut self, n: u8) -> Result<(), Error> { let a = self.get_register_value(Register::A); let value = self.get_register_value(Register::A); - self.set_ioport_value(a, n, value)?; + self.write_ioport_value(a, n, value)?; Ok(()) } @@ -1101,7 +1101,7 @@ impl Z80 { self.port.write_leu16(self.current_clock, addr as Address, value) } - fn get_ioport_value(&mut self, upper: u8, lower: u8) -> Result { + fn read_ioport_value(&mut self, upper: u8, lower: u8) -> Result { let addr = ((upper as Address) << 8) | (lower as Address); if let Some(io) = self.ioport.as_mut() { Ok(io.read_u8(self.current_clock, addr)?) @@ -1110,7 +1110,7 @@ impl Z80 { } } - fn set_ioport_value(&mut self, upper: u8, lower: u8, value: u8) -> Result<(), Error> { + fn write_ioport_value(&mut self, upper: u8, lower: u8, value: u8) -> Result<(), Error> { let addr = ((upper as Address) << 8) | (lower as Address); if let Some(io) = self.ioport.as_mut() { io.write_u8(self.current_clock, addr, value)? @@ -1221,12 +1221,10 @@ impl Z80 { self.set_flags(FLAGS_CARRY_HALF_CARRY, carry_flag | half_carry_flag); } - #[inline(always)] fn get_flag(&self, flag: Flags) -> bool { self.get_flags() & (flag as u8) != 0 } - #[inline(always)] fn set_flag(&mut self, flag: Flags, value: bool) { self.state.reg[Register::F as usize] &= !(flag as u8); if value { @@ -1234,12 +1232,10 @@ impl Z80 { } } - #[inline(always)] fn get_flags(&self) -> u8 { self.state.reg[Register::F as usize] } - #[inline(always)] fn set_flags(&mut self, mask: u8, values: u8) { self.state.reg[Register::F as usize] = (self.state.reg[Register::F as usize] & !mask) | values; } @@ -1273,7 +1269,6 @@ fn sub_words(operand1: u16, operand2: u16) -> (u16, bool, bool, bool) { (result, carry, overflow, half_carry) } -#[inline(always)] fn get_msb(value: u16, size: Size) -> bool { match size { Size::Byte => (value & 0x0080) != 0, diff --git a/tests/rad_tests/latest.txt b/tests/rad_tests/latest.txt index 522af48..81889aa 100644 --- a/tests/rad_tests/latest.txt +++ b/tests/rad_tests/latest.txt @@ -1,4 +1,4 @@ -Last run on 2023-05-14 at commit 7e62a2691c552f3a628ac18b3eaba2a45265abde +Last run on 2023-05-14 at commit aaa7952dd0cf0ab6e33946ce0ae1aa91920e5405 00.json completed, all passed! 01.json completed, all passed! @@ -36,7 +36,7 @@ Last run on 2023-05-14 at commit 7e62a2691c552f3a628ac18b3eaba2a45265abde 1f.json completed, all passed! 20.json completed, all passed! 21.json completed, all passed! -22.json completed: 999 passed, 1 FAILED +22.json completed, all passed! 23.json completed, all passed! 24.json completed, all passed! 25.json completed, all passed! @@ -636,12 +636,12 @@ fd ae.json completed, all passed! fd b6.json completed, all passed! fd be.json completed, all passed! fd e1.json completed, all passed! -fd e3.json completed: 999 passed, 1 FAILED +fd e3.json completed, all passed! fd e5.json completed, all passed! fd e9.json completed, all passed! fd f9.json completed, all passed! fe.json completed, all passed! ff.json completed, all passed! -passed: 629558, failed: 12442, total 98% +passed: 629560, failed: 12440, total 98% completed in 0m 32s diff --git a/tests/rad_tests/src/main.rs b/tests/rad_tests/src/main.rs index 5c5093a..ce4751d 100644 --- a/tests/rad_tests/src/main.rs +++ b/tests/rad_tests/src/main.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use std::time::SystemTime; use std::fs::{self, File}; -use clap::{Parser, ArgEnum}; +use clap::Parser; use flate2::read::GzDecoder; use serde_derive::Deserialize; @@ -20,13 +20,6 @@ use moa_z80::instructions::InterruptMode; use moa_z80::state::Flags; use moa_z80::state::Status; -#[derive(Copy, Clone, PartialEq, Eq, ArgEnum)] -enum Selection { - Include, - Exclude, - ExcludeAddr, - Only, -} #[derive(Parser)] struct Args { @@ -47,11 +40,12 @@ struct Args { /// Check undocumented instructions #[clap(short = 'u', long)] check_undocumented: bool, + /// Check instruction timings + #[clap(short = 't', long)] + check_timings: bool, /// Directory to the test suite to run #[clap(long, default_value = DEFAULT_RAD_TESTS)] testsuite: String, - #[clap(long, short, arg_enum, default_value_t = Selection::Include)] - exceptions: Selection, } fn main() { @@ -90,6 +84,9 @@ struct TestState { ram: Vec<(u16, u8)>, } +#[derive(Debug, Deserialize)] +struct TestCycle(u16, Option, String); + #[derive(Debug, Deserialize)] struct TestPort { addr: u16, @@ -105,6 +102,8 @@ struct TestCase { #[serde(rename(deserialize = "final"))] final_state: TestState, #[serde(default)] + cycles: Vec, + #[serde(default)] ports: Vec, } @@ -279,10 +278,16 @@ fn assert_state(cpu: &Z80, system: &System, io_bus: Rc>, expected: Ok(()) } -fn step_cpu_and_assert(cpu: &mut Z80, system: &System, io_bus: Rc>, case: &TestCase, check_extra_flags: bool) -> Result<(), Error> { - let _clock_elapsed = cpu.step(&system)?; +fn step_cpu_and_assert(cpu: &mut Z80, system: &System, io_bus: Rc>, case: &TestCase, args: &Args) -> Result<(), Error> { + let clock_elapsed = cpu.step(&system)?; - assert_state(&cpu, &system, io_bus, &case.final_state, check_extra_flags, &case.ports)?; + assert_state(&cpu, &system, io_bus, &case.final_state, args.check_extra_flags, &case.ports)?; + if args.check_timings { + let cycles = clock_elapsed / cpu.frequency.period_duration(); + if cycles != case.cycles.len() as Address { + return Err(Error::assertion(&format!("expected instruction to take {} cycles, but took {}", case.cycles.len(), cycles))); + } + } Ok(()) } @@ -291,7 +296,7 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> { let (mut cpu, system, io_bus) = init_execute_test(Z80Type::Z80, &case.initial_state, &case.ports).unwrap(); let mut initial_cpu = cpu.clone(); - let result = step_cpu_and_assert(&mut cpu, &system, io_bus, case, args.check_extra_flags); + let result = step_cpu_and_assert(&mut cpu, &system, io_bus, case, args); match result { Ok(()) => Ok(()), diff --git a/todo.txt b/todo.txt index a80efb7..ccd6718 100644 --- a/todo.txt +++ b/todo.txt @@ -7,10 +7,13 @@ * go through flags on m68k and see if you can fix the remaining ones and/or clean up the implementation +* you could possibly make a Z80MemoryPort type that wraps the BusPort type and which impls Addressable, which can be passed into the decoder + to auto-insert things like the refresh counter, as well as the record all bus timings whenever any mem access is performed * should you make Address a newtype and add From impls for each type of numeric, and add utils to wrap address at certain boundaries and such * should you make a means of storing different kinds of buses? * should you make buses hide their RcRefCell? + * address repeater on ym2612 doesn't seem to work the same, when it's on the 68000 device. The Z80 device doesn't have an affect, but maybe it's not being used * sound doesn't work on a lot of games... is it a problem with the Z80 accessing the YM2612, or the lack of YM timers? or something else? * make the ym generate audio in sync so the DAC timings can be more accurate