Modified to use emulator-hal traits
This commit is contained in:
parent
b4a35641e4
commit
8b274f72cc
|
@ -358,3 +358,25 @@ pub fn dump_slice(data: &[u8], mut count: usize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use emulator_hal::bus::{self, BusAccess};
|
||||||
|
|
||||||
|
//impl bus::Error for Error {}
|
||||||
|
|
||||||
|
//impl ErrorType for BusPort {
|
||||||
|
// type Error = Error;
|
||||||
|
//}
|
||||||
|
|
||||||
|
impl BusAccess<u64, Instant> for BusPort {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn read(&mut self, now: Instant, addr: Address, data: &mut [u8]) -> Result<usize, Self::Error> {
|
||||||
|
<Self as Addressable>::read(self, now, addr, data)?;
|
||||||
|
Ok(data.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, now: Instant, addr: Address, data: &[u8]) -> Result<usize, Self::Error> {
|
||||||
|
<Self as Addressable>::write(self, now, addr, data)?;
|
||||||
|
Ok(data.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
|
||||||
|
use femtos::Instant;
|
||||||
|
use emulator_hal::bus::{self, BusAccess};
|
||||||
|
|
||||||
use moa_core::{System, Error, Address, Addressable, Debuggable};
|
use moa_core::{System, Error, Address, Addressable, Debuggable};
|
||||||
|
|
||||||
use super::state::M68k;
|
use super::state::M68k;
|
||||||
use super::decode::M68kDecoder;
|
use super::decode::M68kDecoder;
|
||||||
use super::execute::M68kCycleExecutor;
|
use super::execute::M68kCycleExecutor;
|
||||||
|
use super::memory::M68kAddress;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct StackTracer {
|
pub struct StackTracer {
|
||||||
|
@ -59,7 +63,7 @@ impl Debuggable for M68k {
|
||||||
"ds" | "stack" | "dumpstack" => {
|
"ds" | "stack" | "dumpstack" => {
|
||||||
println!("Stack:");
|
println!("Stack:");
|
||||||
for addr in &self.debugger.stack_tracer.calls {
|
for addr in &self.debugger.stack_tracer.calls {
|
||||||
println!(" {:08x}", self.port.read_beu32(system.clock, *addr as Address)?);
|
println!(" {:08x}", BusAccess::read_beu32(&mut self.port, system.clock, *addr as Address)?);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"so" | "stepout" => {
|
"so" | "stepout" => {
|
||||||
|
@ -71,7 +75,10 @@ impl Debuggable for M68k {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> M68kCycleExecutor<'a> {
|
impl<'a, Bus> M68kCycleExecutor<'a, Bus>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
pub fn check_breakpoints(&mut self) -> Result<(), Error> {
|
pub fn check_breakpoints(&mut self) -> Result<(), Error> {
|
||||||
for breakpoint in &self.debugger.breakpoints {
|
for breakpoint in &self.debugger.breakpoints {
|
||||||
if *breakpoint == self.state.pc {
|
if *breakpoint == self.state.pc {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
use femtos::Instant;
|
use femtos::Instant;
|
||||||
|
use emulator_hal::bus::{self, BusAccess, BusError};
|
||||||
|
|
||||||
use moa_core::{Address, Addressable, BusPort};
|
use moa_core::{Error, Address, Addressable};
|
||||||
|
|
||||||
use crate::state::{M68kType, M68kError, Exceptions};
|
use crate::state::{M68kType, M68kError, Exceptions};
|
||||||
use crate::memory::M68kBusPort;
|
use crate::memory::{M68kBusPort, M68kAddress};
|
||||||
use crate::instructions::{
|
use crate::instructions::{
|
||||||
Size,
|
Size,
|
||||||
Sign,
|
Sign,
|
||||||
|
@ -49,8 +50,11 @@ pub struct M68kDecoder {
|
||||||
pub instruction: Instruction,
|
pub instruction: Instruction,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InstructionDecoding<'a> {
|
pub struct InstructionDecoding<'a, Bus>
|
||||||
port: &'a mut BusPort,
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
|
port: &'a mut Bus,
|
||||||
memory: &'a mut M68kBusPort,
|
memory: &'a mut M68kBusPort,
|
||||||
decoder: &'a mut M68kDecoder,
|
decoder: &'a mut M68kDecoder,
|
||||||
}
|
}
|
||||||
|
@ -76,7 +80,10 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_at(&mut self, port: &mut BusPort, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> {
|
pub fn decode_at<Bus>(&mut self, port: &mut Bus, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError<Bus::Error>>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
self.init(is_supervisor, start);
|
self.init(is_supervisor, start);
|
||||||
let mut decoding = InstructionDecoding {
|
let mut decoding = InstructionDecoding {
|
||||||
port,
|
port,
|
||||||
|
@ -87,7 +94,10 @@ impl M68kDecoder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_disassembly(&mut self, port: &mut BusPort, memory: &mut M68kBusPort, start: u32, length: u32) {
|
pub fn dump_disassembly<Bus>(&mut self, port: &mut Bus, memory: &mut M68kBusPort, start: u32, length: u32)
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
let mut next = start;
|
let mut next = start;
|
||||||
while next < (start + length) {
|
while next < (start + length) {
|
||||||
match self.decode_at(port, memory, self.is_supervisor, next) {
|
match self.decode_at(port, memory, self.is_supervisor, next) {
|
||||||
|
@ -109,8 +119,11 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_decoded(&mut self, clock: Instant, port: &mut BusPort) {
|
pub fn dump_decoded<Bus>(&mut self, clock: Instant, port: &mut Bus)
|
||||||
let ins_data: Result<String, M68kError> =
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
|
let ins_data: Result<String, M68kError<Bus::Error>> =
|
||||||
(0..((self.end - self.start) / 2)).map(|offset|
|
(0..((self.end - self.start) / 2)).map(|offset|
|
||||||
Ok(format!("{:04x} ", port.read_beu16(clock, (self.start + (offset * 2)) as Address).unwrap()))
|
Ok(format!("{:04x} ", port.read_beu16(clock, (self.start + (offset * 2)) as Address).unwrap()))
|
||||||
).collect();
|
).collect();
|
||||||
|
@ -118,9 +131,12 @@ impl M68kDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InstructionDecoding<'a> {
|
impl<'a, Bus> InstructionDecoding<'a, Bus>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_next(&mut self) -> Result<Instruction, M68kError> {
|
pub fn decode_next(&mut self) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let ins = self.read_instruction_word()?;
|
let ins = self.read_instruction_word()?;
|
||||||
self.decoder.instruction_word = ins;
|
self.decoder.instruction_word = ins;
|
||||||
|
|
||||||
|
@ -146,7 +162,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_bit_ops(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_bit_ops(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let optype = (ins & 0x0F00) >> 8;
|
let optype = (ins & 0x0F00) >> 8;
|
||||||
|
|
||||||
if (ins & 0x13F) == 0x03C {
|
if (ins & 0x13F) == 0x03C {
|
||||||
|
@ -221,14 +237,14 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_move_byte(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_move_byte(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let src = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
|
let src = self.decode_lower_effective_address(ins, Some(Size::Byte))?;
|
||||||
let dest = self.decode_upper_effective_address(ins, Some(Size::Byte))?;
|
let dest = self.decode_upper_effective_address(ins, Some(Size::Byte))?;
|
||||||
Ok(Instruction::MOVE(src, dest, Size::Byte))
|
Ok(Instruction::MOVE(src, dest, Size::Byte))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_move_long(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_move_long(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let src = self.decode_lower_effective_address(ins, Some(Size::Long))?;
|
let src = self.decode_lower_effective_address(ins, Some(Size::Long))?;
|
||||||
let dest = self.decode_upper_effective_address(ins, Some(Size::Long))?;
|
let dest = self.decode_upper_effective_address(ins, Some(Size::Long))?;
|
||||||
if let Target::DirectAReg(reg) = dest {
|
if let Target::DirectAReg(reg) = dest {
|
||||||
|
@ -239,7 +255,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_move_word(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_move_word(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let src = self.decode_lower_effective_address(ins, Some(Size::Word))?;
|
let src = self.decode_lower_effective_address(ins, Some(Size::Word))?;
|
||||||
let dest = self.decode_upper_effective_address(ins, Some(Size::Word))?;
|
let dest = self.decode_upper_effective_address(ins, Some(Size::Word))?;
|
||||||
if let Target::DirectAReg(reg) = dest {
|
if let Target::DirectAReg(reg) = dest {
|
||||||
|
@ -250,7 +266,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_misc(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_misc(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let ins_0f00 = ins & 0xF00;
|
let ins_0f00 = ins & 0xF00;
|
||||||
let ins_00f0 = ins & 0x0F0;
|
let ins_00f0 = ins & 0x0F0;
|
||||||
|
|
||||||
|
@ -421,7 +437,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_addq_subq(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_addq_subq(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
match get_size(ins) {
|
match get_size(ins) {
|
||||||
Some(size) => {
|
Some(size) => {
|
||||||
let target = self.decode_lower_effective_address(ins, Some(size))?;
|
let target = self.decode_lower_effective_address(ins, Some(size))?;
|
||||||
|
@ -459,7 +475,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_branch(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_branch(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let mut disp = ((ins & 0xFF) as i8) as i32;
|
let mut disp = ((ins & 0xFF) as i8) as i32;
|
||||||
if disp == 0 {
|
if disp == 0 {
|
||||||
disp = (self.read_instruction_word()? as i16) as i32;
|
disp = (self.read_instruction_word()? as i16) as i32;
|
||||||
|
@ -475,7 +491,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_moveq(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_moveq(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
if (ins & 0x0100) != 0 {
|
if (ins & 0x0100) != 0 {
|
||||||
return Err(M68kError::Exception(Exceptions::IllegalInstruction));
|
return Err(M68kError::Exception(Exceptions::IllegalInstruction));
|
||||||
}
|
}
|
||||||
|
@ -485,7 +501,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_div_or(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_div_or(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
|
||||||
if (ins & 0x1F0) == 0x100 {
|
if (ins & 0x1F0) == 0x100 {
|
||||||
|
@ -509,7 +525,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_sub(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_sub(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let dir = (ins & 0x0100) >> 8;
|
let dir = (ins & 0x0100) >> 8;
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
@ -540,7 +556,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_cmp_eor(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_cmp_eor(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let optype = (ins & 0x0100) >> 8;
|
let optype = (ins & 0x0100) >> 8;
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
@ -567,7 +583,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_mul_and(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_mul_and(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
|
||||||
if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 {
|
if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 {
|
||||||
|
@ -600,7 +616,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode_group_add(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_add(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let dir = (ins & 0x0100) >> 8;
|
let dir = (ins & 0x0100) >> 8;
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
|
@ -630,7 +646,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_group_shift(&mut self, ins: u16) -> Result<Instruction, M68kError> {
|
fn decode_group_shift(&mut self, ins: u16) -> Result<Instruction, M68kError<Bus::Error>> {
|
||||||
match get_size(ins) {
|
match get_size(ins) {
|
||||||
Some(size) => {
|
Some(size) => {
|
||||||
let target = Target::DirectDReg(get_low_reg(ins));
|
let target = Target::DirectDReg(get_low_reg(ins));
|
||||||
|
@ -716,31 +732,31 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_instruction_word(&mut self) -> Result<u16, M68kError> {
|
fn read_instruction_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
|
||||||
let word = self.memory.read_instruction_word(self.port, self.decoder.is_supervisor, self.decoder.end)?;
|
let word = self.memory.read_instruction_word(self.port, self.decoder.is_supervisor, self.decoder.end)?;
|
||||||
self.decoder.end += 2;
|
self.decoder.end += 2;
|
||||||
Ok(word)
|
Ok(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_instruction_long(&mut self) -> Result<u32, M68kError> {
|
fn read_instruction_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let word = self.memory.read_instruction_long(self.port, self.decoder.is_supervisor, self.decoder.end)?;
|
let word = self.memory.read_instruction_long(self.port, self.decoder.is_supervisor, self.decoder.end)?;
|
||||||
self.decoder.end += 4;
|
self.decoder.end += 4;
|
||||||
Ok(word)
|
Ok(word)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_lower_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
fn decode_lower_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError<Bus::Error>> {
|
||||||
let reg = get_low_reg(ins);
|
let reg = get_low_reg(ins);
|
||||||
let mode = get_low_mode(ins);
|
let mode = get_low_mode(ins);
|
||||||
self.get_mode_as_target(mode, reg, size)
|
self.get_mode_as_target(mode, reg, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_upper_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
fn decode_upper_effective_address(&mut self, ins: u16, size: Option<Size>) -> Result<Target, M68kError<Bus::Error>> {
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let mode = get_high_mode(ins);
|
let mode = get_high_mode(ins);
|
||||||
self.get_mode_as_target(mode, reg, size)
|
self.get_mode_as_target(mode, reg, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_extension_displacement(&mut self, select: u16) -> Result<i32, M68kError> {
|
fn get_extension_displacement(&mut self, select: u16) -> Result<i32, M68kError<Bus::Error>> {
|
||||||
let result = match select {
|
let result = match select {
|
||||||
0b00 | 0b01 => 0,
|
0b00 | 0b01 => 0,
|
||||||
0b10 => sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word),
|
0b10 => sign_extend_to_long(self.read_instruction_word()? as u32, Size::Word),
|
||||||
|
@ -750,7 +766,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_extension_word(&mut self, areg: Option<u8>) -> Result<Target, M68kError> {
|
fn decode_extension_word(&mut self, areg: Option<u8>) -> Result<Target, M68kError<Bus::Error>> {
|
||||||
let brief_extension = self.read_instruction_word()?;
|
let brief_extension = self.read_instruction_word()?;
|
||||||
|
|
||||||
let use_brief = (brief_extension & 0x0100) == 0;
|
let use_brief = (brief_extension & 0x0100) == 0;
|
||||||
|
@ -803,7 +819,7 @@ impl<'a> InstructionDecoding<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_mode_as_target(&mut self, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError> {
|
pub(super) fn get_mode_as_target(&mut self, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError<Bus::Error>> {
|
||||||
let value = match mode {
|
let value = match mode {
|
||||||
0b000 => Target::DirectDReg(reg),
|
0b000 => Target::DirectDReg(reg),
|
||||||
0b001 => Target::DirectAReg(reg),
|
0b001 => Target::DirectAReg(reg),
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
use femtos::{Instant, Duration};
|
use femtos::{Instant, Duration};
|
||||||
|
use emulator_hal::bus::{self, BusAccess, BusAdapter};
|
||||||
|
|
||||||
use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable, BusPort};
|
use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable, BusPort};
|
||||||
|
|
||||||
use crate::state::{M68k, M68kType, M68kError, M68kState, ClockCycles, Status, Flags, Exceptions, InterruptPriority};
|
use crate::state::{M68k, M68kType, M68kError, M68kState, ClockCycles, Status, Flags, Exceptions, InterruptPriority};
|
||||||
use crate::memory::{MemType, MemAccess, M68kBusPort};
|
use crate::memory::{MemType, MemAccess, M68kBusPort, M68kAddress};
|
||||||
use crate::decode::M68kDecoder;
|
use crate::decode::M68kDecoder;
|
||||||
use crate::debugger::M68kDebugger;
|
use crate::debugger::M68kDebugger;
|
||||||
use crate::timing::M68kInstructionTiming;
|
use crate::timing::M68kInstructionTiming;
|
||||||
|
@ -65,24 +66,40 @@ impl M68kCycle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn begin<'a>(mut self, cpu: &'a mut M68k) -> M68kCycleExecutor<'a> {
|
pub fn begin<'a>(mut self, cpu: &'a mut M68k) -> M68kCycleExecutor<'a, bus::BusAdapter<M68kAddress, u64, Instant, &'a mut BusPort>> {
|
||||||
|
let adapter = bus::BusAdapter {
|
||||||
|
bus: &mut cpu.port,
|
||||||
|
translate: translate_address,
|
||||||
|
instant: core::marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
M68kCycleExecutor {
|
M68kCycleExecutor {
|
||||||
state: &mut cpu.state,
|
state: &mut cpu.state,
|
||||||
port: &mut cpu.port,
|
port: adapter,
|
||||||
debugger: &mut cpu.debugger,
|
debugger: &mut cpu.debugger,
|
||||||
cycle: self,
|
cycle: self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct M68kCycleExecutor<'a> {
|
fn translate_address(addr_in: M68kAddress) -> u64 {
|
||||||
|
addr_in as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct M68kCycleExecutor<'a, Bus>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
pub state: &'a mut M68kState,
|
pub state: &'a mut M68kState,
|
||||||
pub port: &'a mut BusPort,
|
pub port: Bus,
|
||||||
pub debugger: &'a mut M68kDebugger,
|
pub debugger: &'a mut M68kDebugger,
|
||||||
pub cycle: M68kCycle,
|
pub cycle: M68kCycle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> M68kCycleExecutor<'a> {
|
impl<'a, Bus> M68kCycleExecutor<'a, Bus>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dump_state(&mut self) {
|
pub fn dump_state(&mut self) {
|
||||||
println!("Status: {:?}", self.state.status);
|
println!("Status: {:?}", self.state.status);
|
||||||
|
@ -96,7 +113,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
|
|
||||||
println!("Current Instruction: {:#010x} {:?}", self.cycle.decoder.start, self.cycle.decoder.instruction);
|
println!("Current Instruction: {:#010x} {:?}", self.cycle.decoder.start, self.cycle.decoder.instruction);
|
||||||
println!();
|
println!();
|
||||||
self.cycle.memory.dump_memory(self.port, self.state.ssp, 0x40);
|
self.cycle.memory.dump_memory(&mut self.port, self.state.ssp, 0x40);
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,20 +153,21 @@ impl Transmutable for M68k {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<M68kError> for Error {
|
impl<BusError: bus::BusError> From<M68kError<BusError>> for Error {
|
||||||
fn from(err: M68kError) -> Self {
|
fn from(err: M68kError<BusError>) -> Self {
|
||||||
match err {
|
match err {
|
||||||
M68kError::Halted => Self::Other("cpu halted".to_string()),
|
M68kError::Halted => Self::Other("cpu halted".to_string()),
|
||||||
M68kError::Exception(ex) => Self::Processor(ex as u32),
|
M68kError::Exception(ex) => Self::Processor(ex as u32),
|
||||||
M68kError::Interrupt(num) => Self::Processor(num as u32),
|
M68kError::Interrupt(num) => Self::Processor(num as u32),
|
||||||
M68kError::Breakpoint => Self::Breakpoint("breakpoint".to_string()),
|
M68kError::Breakpoint => Self::Breakpoint("breakpoint".to_string()),
|
||||||
M68kError::InvalidTarget(target) => Self::new(target.to_string()),
|
M68kError::InvalidTarget(target) => Self::new(target.to_string()),
|
||||||
|
M68kError::BusError(msg) => Self::Other(format!("{:?}", msg)),
|
||||||
M68kError::Other(msg) => Self::Other(msg),
|
M68kError::Other(msg) => Self::Other(msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for M68kError {
|
impl<BusError> From<Error> for M68kError<BusError> {
|
||||||
fn from(err: Error) -> Self {
|
fn from(err: Error) -> Self {
|
||||||
match err {
|
match err {
|
||||||
Error::Processor(ex) => M68kError::Interrupt(ex as u8),
|
Error::Processor(ex) => M68kError::Interrupt(ex as u8),
|
||||||
|
@ -159,15 +177,18 @@ impl From<Error> for M68kError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> M68kCycleExecutor<'a> {
|
impl<'a, Bus> M68kCycleExecutor<'a, Bus>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn step(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
pub fn step(&mut self, system: &System) -> Result<ClockCycles, M68kError<Bus::Error>> {
|
||||||
let result = self.step_one(system);
|
let result = self.step_one(system);
|
||||||
self.process_error(result, 4)
|
self.process_error(result, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn process_error<T>(&mut self, result: Result<T, M68kError>, ok: T) -> Result<T, M68kError> {
|
pub fn process_error<T>(&mut self, result: Result<T, M68kError<Bus::Error>>, ok: T) -> Result<T, M68kError<Bus::Error>> {
|
||||||
match result {
|
match result {
|
||||||
Ok(value) => Ok(value),
|
Ok(value) => Ok(value),
|
||||||
Err(M68kError::Exception(ex)) => {
|
Err(M68kError::Exception(ex)) => {
|
||||||
|
@ -183,34 +204,36 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn step_one(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
pub fn step_one(&mut self, system: &System) -> Result<ClockCycles, M68kError<Bus::Error>> {
|
||||||
match self.state.status {
|
match self.state.status {
|
||||||
Status::Init => self.reset_cpu(),
|
Status::Init => self.reset_cpu(),
|
||||||
Status::Stopped => Err(M68kError::Halted),
|
Status::Stopped => Err(M68kError::Halted),
|
||||||
Status::Running => self.cycle_one(system),
|
Status::Running => self.cycle_one(system),
|
||||||
}
|
}?;
|
||||||
|
Ok(self.cycle.timing.calculate_clocks())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reset_cpu(&mut self) -> Result<ClockCycles, M68kError> {
|
pub fn reset_cpu(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.state.ssp = self.get_address_sized(0, Size::Long)?;
|
self.state.ssp = self.get_address_sized(0, Size::Long)?;
|
||||||
self.state.pc = self.get_address_sized(4, Size::Long)?;
|
self.state.pc = self.get_address_sized(4, Size::Long)?;
|
||||||
self.state.status = Status::Running;
|
self.state.status = Status::Running;
|
||||||
Ok(16)
|
self.cycle.timing.performed_reset();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cycle_one(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
pub fn cycle_one(&mut self, system: &System) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.check_breakpoints()?;
|
self.check_breakpoints()?;
|
||||||
|
|
||||||
self.decode_and_execute()?;
|
self.decode_and_execute()?;
|
||||||
|
|
||||||
self.check_pending_interrupts(system)?;
|
self.check_pending_interrupts(system)?;
|
||||||
Ok(self.cycle.timing.calculate_clocks(false, 1))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError> {
|
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError<Bus::Error>> {
|
||||||
// TODO this could move somewhere else
|
// TODO this could move somewhere else
|
||||||
self.state.pending_ipl = match system.get_interrupt_controller().check() {
|
self.state.pending_ipl = match system.get_interrupt_controller().check() {
|
||||||
(true, priority) => InterruptPriority::from_u8(priority),
|
(true, priority) => InterruptPriority::from_u8(priority),
|
||||||
|
@ -268,7 +291,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> {
|
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError<Bus::Error>> {
|
||||||
log::debug!("{}: raising exception {}", DEV_NAME, number);
|
log::debug!("{}: raising exception {}", DEV_NAME, number);
|
||||||
|
|
||||||
if number == Exceptions::BusError as u8 || number == Exceptions::AddressError as u8 {
|
if number == Exceptions::BusError as u8 || number == Exceptions::AddressError as u8 {
|
||||||
|
@ -284,7 +307,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_group0_exception(&mut self, number: u8) -> Result<(), M68kError> {
|
fn setup_group0_exception(&mut self, number: u8) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let sr = self.state.sr;
|
let sr = self.state.sr;
|
||||||
let ins_word = self.cycle.decoder.instruction_word;
|
let ins_word = self.cycle.decoder.instruction_word;
|
||||||
let extra_code = self.cycle.memory.request.get_type_code();
|
let extra_code = self.cycle.memory.request.get_type_code();
|
||||||
|
@ -313,7 +336,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> {
|
fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let sr = self.state.sr;
|
let sr = self.state.sr;
|
||||||
self.cycle.memory.request.i_n_bit = true;
|
self.cycle.memory.request.i_n_bit = true;
|
||||||
|
|
||||||
|
@ -339,14 +362,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_and_execute(&mut self) -> Result<(), M68kError> {
|
pub fn decode_and_execute(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.decode_next()?;
|
self.decode_next()?;
|
||||||
self.execute_current()?;
|
self.execute_current()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_next(&mut self) -> Result<(), M68kError> {
|
pub fn decode_next(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let is_supervisor = self.is_supervisor();
|
let is_supervisor = self.is_supervisor();
|
||||||
self.cycle.decoder.decode_at(&mut self.port, &mut self.cycle.memory, is_supervisor, self.state.pc)?;
|
self.cycle.decoder.decode_at(&mut self.port, &mut self.cycle.memory, is_supervisor, self.state.pc)?;
|
||||||
|
|
||||||
|
@ -358,7 +381,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn execute_current(&mut self) -> Result<(), M68kError> {
|
pub fn execute_current(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
match self.cycle.decoder.instruction {
|
match self.cycle.decoder.instruction {
|
||||||
Instruction::ABCD(src, dest) => self.execute_abcd(src, dest),
|
Instruction::ABCD(src, dest) => self.execute_abcd(src, dest),
|
||||||
Instruction::ADD(src, dest, size) => self.execute_add(src, dest, size),
|
Instruction::ADD(src, dest, size) => self.execute_add(src, dest, size),
|
||||||
|
@ -454,7 +477,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_abcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError> {
|
fn execute_abcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Byte, Used::Once)?;
|
let src_val = self.get_target_value(src, Size::Byte, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
||||||
|
|
||||||
|
@ -478,7 +501,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_add(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_add(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let (result, carry) = overflowing_add_sized(dest_val, src_val, size);
|
let (result, carry) = overflowing_add_sized(dest_val, src_val, size);
|
||||||
|
@ -489,7 +512,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_adda(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError> {
|
fn execute_adda(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32;
|
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);
|
let dest_val = *self.get_a_reg_mut(dest);
|
||||||
let (result, _) = overflowing_add_sized(dest_val, src_val, Size::Long);
|
let (result, _) = overflowing_add_sized(dest_val, src_val, Size::Long);
|
||||||
|
@ -497,7 +520,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_addx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_addx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let extend = self.get_flag(Flags::Extend) as u32;
|
let extend = self.get_flag(Flags::Extend) as u32;
|
||||||
|
@ -518,7 +541,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_and(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_and(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let result = get_value_sized(dest_val & src_val, size);
|
let result = get_value_sized(dest_val & src_val, size);
|
||||||
|
@ -527,18 +550,18 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_and_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
fn execute_and_to_ccr(&mut self, value: u8) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) & (value as u16));
|
self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) & (value as u16));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_and_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
fn execute_and_to_sr(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
self.set_sr(self.state.sr & value);
|
self.set_sr(self.state.sr & value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_asl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_asl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let value = self.get_target_value(target, size, Used::Twice)?;
|
let value = self.get_target_value(target, size, Used::Twice)?;
|
||||||
|
|
||||||
|
@ -558,7 +581,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_asr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_asr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let value = self.get_target_value(target, size, Used::Twice)?;
|
let value = self.get_target_value(target, size, Used::Twice)?;
|
||||||
|
|
||||||
|
@ -591,7 +614,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), M68kError> {
|
fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let should_branch = self.get_current_condition(cond);
|
let should_branch = self.get_current_condition(cond);
|
||||||
if should_branch {
|
if should_branch {
|
||||||
if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
||||||
|
@ -602,7 +625,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bra(&mut self, offset: i32) -> Result<(), M68kError> {
|
fn execute_bra(&mut self, offset: i32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
if let Err(err) = self.set_pc(self.cycle.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
@ -610,7 +633,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bsr(&mut self, offset: i32) -> Result<(), M68kError> {
|
fn execute_bsr(&mut self, offset: i32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.push_long(self.state.pc)?;
|
self.push_long(self.state.pc)?;
|
||||||
let sp = *self.get_stack_pointer_mut();
|
let sp = *self.get_stack_pointer_mut();
|
||||||
self.debugger.stack_tracer.push_return(sp);
|
self.debugger.stack_tracer.push_return(sp);
|
||||||
|
@ -621,7 +644,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bchg(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_bchg(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||||
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
||||||
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
||||||
|
@ -630,7 +653,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bclr(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_bclr(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||||
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
||||||
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
||||||
|
@ -639,7 +662,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bset(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_bset(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||||
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
||||||
let mask = self.set_bit_test_flags(value, bitnum, size);
|
let mask = self.set_bit_test_flags(value, bitnum, size);
|
||||||
|
@ -648,14 +671,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_btst(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_btst(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||||
let value = self.get_target_value(target, size, Used::Once)?;
|
let value = self.get_target_value(target, size, Used::Once)?;
|
||||||
self.set_bit_test_flags(value, bitnum, size);
|
self.set_bit_test_flags(value, bitnum, size);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bfchg(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
fn execute_bfchg(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||||
|
@ -665,7 +688,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bfclr(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
fn execute_bfclr(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||||
|
@ -675,7 +698,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bfexts(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError> {
|
fn execute_bfexts(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||||
|
@ -691,7 +714,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bfextu(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError> {
|
fn execute_bfextu(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||||
|
@ -701,7 +724,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bfset(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
fn execute_bfset(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||||
|
@ -711,7 +734,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_bftst(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
fn execute_bftst(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||||
let mask = get_bit_field_mask(offset, width);
|
let mask = get_bit_field_mask(offset, width);
|
||||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||||
|
@ -720,7 +743,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_chk(&mut self, target: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
fn execute_chk(&mut self, target: Target, reg: Register, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let upper_bound = sign_extend_to_long(self.get_target_value(target, size, Used::Once)?, size);
|
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);
|
let dreg = sign_extend_to_long(self.state.d_reg[reg as usize], size);
|
||||||
|
|
||||||
|
@ -736,7 +759,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
if self.cycle.decoder.cputype == M68kType::MC68000 {
|
if self.cycle.decoder.cputype == M68kType::MC68000 {
|
||||||
self.get_target_value(target, size, Used::Twice)?;
|
self.get_target_value(target, size, Used::Twice)?;
|
||||||
self.set_target_value(target, 0, size, Used::Twice)?;
|
self.set_target_value(target, 0, size, Used::Twice)?;
|
||||||
|
@ -748,7 +771,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_cmp(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_cmp(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Once)?;
|
let dest_val = self.get_target_value(dest, size, Used::Once)?;
|
||||||
let (result, carry) = overflowing_sub_sized(dest_val, src_val, size);
|
let (result, carry) = overflowing_sub_sized(dest_val, src_val, size);
|
||||||
|
@ -757,7 +780,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_cmpa(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
fn execute_cmpa(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32;
|
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);
|
let dest_val = *self.get_a_reg_mut(reg);
|
||||||
let (result, carry) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
let (result, carry) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
||||||
|
@ -766,7 +789,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_dbcc(&mut self, cond: Condition, reg: Register, offset: i16) -> Result<(), M68kError> {
|
fn execute_dbcc(&mut self, cond: Condition, reg: Register, offset: i16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let condition_true = self.get_current_condition(cond);
|
let condition_true = self.get_current_condition(cond);
|
||||||
if !condition_true {
|
if !condition_true {
|
||||||
let next = ((get_value_sized(self.state.d_reg[reg as usize], Size::Word) as u16) as i16).wrapping_sub(1);
|
let next = ((get_value_sized(self.state.d_reg[reg as usize], Size::Word) as u16) as i16).wrapping_sub(1);
|
||||||
|
@ -781,7 +804,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_divw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError> {
|
fn execute_divw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Word, Used::Once)?;
|
let src_val = self.get_target_value(src, Size::Word, Used::Once)?;
|
||||||
if src_val == 0 {
|
if src_val == 0 {
|
||||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||||
|
@ -821,7 +844,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_divl(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError> {
|
fn execute_divl(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Long, Used::Once)?;
|
let src_val = self.get_target_value(src, Size::Long, Used::Once)?;
|
||||||
if src_val == 0 {
|
if src_val == 0 {
|
||||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||||
|
@ -854,7 +877,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_eor(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_eor(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let result = get_value_sized(dest_val ^ src_val, size);
|
let result = get_value_sized(dest_val ^ src_val, size);
|
||||||
|
@ -863,18 +886,18 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_eor_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
fn execute_eor_to_ccr(&mut self, value: u8) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16)));
|
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_eor_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
fn execute_eor_to_sr(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
self.set_sr(self.state.sr ^ value);
|
self.set_sr(self.state.sr ^ value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_exg(&mut self, target1: Target, target2: Target) -> Result<(), M68kError> {
|
fn execute_exg(&mut self, target1: Target, target2: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value1 = self.get_target_value(target1, Size::Long, Used::Twice)?;
|
let value1 = self.get_target_value(target1, Size::Long, Used::Twice)?;
|
||||||
let value2 = self.get_target_value(target2, Size::Long, Used::Twice)?;
|
let value2 = self.get_target_value(target2, Size::Long, Used::Twice)?;
|
||||||
self.set_target_value(target1, value2, Size::Long, Used::Twice)?;
|
self.set_target_value(target1, value2, Size::Long, Used::Twice)?;
|
||||||
|
@ -882,7 +905,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_ext(&mut self, reg: Register, from_size: Size, to_size: Size) -> Result<(), M68kError> {
|
fn execute_ext(&mut self, reg: Register, from_size: Size, to_size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let input = get_value_sized(self.state.d_reg[reg as usize], from_size);
|
let input = get_value_sized(self.state.d_reg[reg as usize], from_size);
|
||||||
let result = match (from_size, to_size) {
|
let result = match (from_size, to_size) {
|
||||||
(Size::Byte, Size::Word) => ((((input as u8) as i8) as i16) as u16) as u32,
|
(Size::Byte, Size::Word) => ((((input as u8) as i8) as i16) as u16) as u32,
|
||||||
|
@ -895,12 +918,12 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_illegal(&mut self) -> Result<(), M68kError> {
|
fn execute_illegal(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.exception(Exceptions::IllegalInstruction as u8, false)?;
|
self.exception(Exceptions::IllegalInstruction as u8, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_jmp(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_jmp(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let addr = self.get_target_address(target)?;
|
let addr = self.get_target_address(target)?;
|
||||||
if let Err(err) = self.set_pc(addr) {
|
if let Err(err) = self.set_pc(addr) {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
|
@ -909,7 +932,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_jsr(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_jsr(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let previous_pc = self.state.pc;
|
let previous_pc = self.state.pc;
|
||||||
let addr = self.get_target_address(target)?;
|
let addr = self.get_target_address(target)?;
|
||||||
if let Err(err) = self.set_pc(addr) {
|
if let Err(err) = self.set_pc(addr) {
|
||||||
|
@ -924,14 +947,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_lea(&mut self, target: Target, reg: Register) -> Result<(), M68kError> {
|
fn execute_lea(&mut self, target: Target, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.get_target_address(target)?;
|
let value = self.get_target_address(target)?;
|
||||||
let addr = self.get_a_reg_mut(reg);
|
let addr = self.get_a_reg_mut(reg);
|
||||||
*addr = value;
|
*addr = value;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_link(&mut self, reg: Register, offset: i32) -> Result<(), M68kError> {
|
fn execute_link(&mut self, reg: Register, offset: i32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
*self.get_stack_pointer_mut() -= 4;
|
*self.get_stack_pointer_mut() -= 4;
|
||||||
let sp = *self.get_stack_pointer_mut();
|
let sp = *self.get_stack_pointer_mut();
|
||||||
let value = *self.get_a_reg_mut(reg);
|
let value = *self.get_a_reg_mut(reg);
|
||||||
|
@ -941,7 +964,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_lsl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_lsl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -953,7 +976,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_lsr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_lsr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -976,14 +999,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
self.set_logic_flags(src_val, size);
|
self.set_logic_flags(src_val, size);
|
||||||
self.set_target_value(dest, src_val, size, Used::Once)?;
|
self.set_target_value(dest, src_val, size, Used::Once)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_movea(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
fn execute_movea(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let src_val = sign_extend_to_long(src_val, size) as u32;
|
let src_val = sign_extend_to_long(src_val, size) as u32;
|
||||||
let addr = self.get_a_reg_mut(reg);
|
let addr = self.get_a_reg_mut(reg);
|
||||||
|
@ -991,26 +1014,26 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_move_from_sr(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_move_from_sr(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
self.set_target_value(target, self.state.sr as u32, Size::Word, Used::Once)?;
|
self.set_target_value(target, self.state.sr as u32, Size::Word, Used::Once)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_move_to_sr(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_move_to_sr(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
||||||
self.set_sr(value);
|
self.set_sr(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_move_to_ccr(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_move_to_ccr(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
||||||
self.set_sr((self.state.sr & 0xFF00) | (value & 0x00FF));
|
self.set_sr((self.state.sr & 0xFF00) | (value & 0x00FF));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_movec(&mut self, target: Target, control_reg: ControlRegister, dir: Direction) -> Result<(), M68kError> {
|
fn execute_movec(&mut self, target: Target, control_reg: ControlRegister, dir: Direction) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
match dir {
|
match dir {
|
||||||
Direction::FromTarget => {
|
Direction::FromTarget => {
|
||||||
|
@ -1027,7 +1050,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), M68kError> {
|
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let addr = self.get_target_address(target)?;
|
let addr = self.get_target_address(target)?;
|
||||||
|
|
||||||
// If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored
|
// If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored
|
||||||
|
@ -1074,7 +1097,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_memory_to_registers(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
fn move_memory_to_registers(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
self.state.d_reg[i] = sign_extend_to_long(self.get_address_sized(addr as Address, size)?, size) as u32;
|
self.state.d_reg[i] = sign_extend_to_long(self.get_address_sized(addr as Address, size)?, size) as u32;
|
||||||
|
@ -1092,7 +1115,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_registers_to_memory(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
fn move_registers_to_memory(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
self.set_address_sized(addr as Address, self.state.d_reg[i], size)?;
|
self.set_address_sized(addr as Address, self.state.d_reg[i], size)?;
|
||||||
|
@ -1111,7 +1134,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_registers_to_memory_reverse(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
fn move_registers_to_memory_reverse(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
for i in (0..8).rev() {
|
for i in (0..8).rev() {
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
let value = *self.get_a_reg_mut(i);
|
let value = *self.get_a_reg_mut(i);
|
||||||
|
@ -1130,7 +1153,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_movep(&mut self, dreg: Register, areg: Register, offset: i16, size: Size, dir: Direction) -> Result<(), M68kError> {
|
fn execute_movep(&mut self, dreg: Register, areg: Register, offset: i16, size: Size, dir: Direction) -> Result<(), M68kError<Bus::Error>> {
|
||||||
match dir {
|
match dir {
|
||||||
Direction::ToTarget => {
|
Direction::ToTarget => {
|
||||||
let mut shift = (size.in_bits() as i32) - 8;
|
let mut shift = (size.in_bits() as i32) - 8;
|
||||||
|
@ -1156,14 +1179,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_moveq(&mut self, data: u8, reg: Register) -> Result<(), M68kError> {
|
fn execute_moveq(&mut self, data: u8, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
|
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
|
||||||
self.state.d_reg[reg as usize] = value;
|
self.state.d_reg[reg as usize] = value;
|
||||||
self.set_logic_flags(value, Size::Long);
|
self.set_logic_flags(value, Size::Long);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_moveusp(&mut self, target: Target, dir: Direction) -> Result<(), M68kError> {
|
fn execute_moveusp(&mut self, target: Target, dir: Direction) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
match dir {
|
match dir {
|
||||||
Direction::ToTarget => self.set_target_value(target, self.state.usp, Size::Long, Used::Once)?,
|
Direction::ToTarget => self.set_target_value(target, self.state.usp, Size::Long, Used::Once)?,
|
||||||
|
@ -1172,7 +1195,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_mulw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError> {
|
fn execute_mulw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Word, Used::Once)?;
|
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);
|
let dest_val = get_value_sized(self.state.d_reg[dest as usize], Size::Word);
|
||||||
let result = match sign {
|
let result = match sign {
|
||||||
|
@ -1185,7 +1208,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_mull(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError> {
|
fn execute_mull(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Long, Used::Once)?;
|
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);
|
let dest_val = get_value_sized(self.state.d_reg[dest_l as usize], Size::Long);
|
||||||
let result = match sign {
|
let result = match sign {
|
||||||
|
@ -1201,14 +1224,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_nbcd(&mut self, dest: Target) -> Result<(), M68kError> {
|
fn execute_nbcd(&mut self, dest: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
||||||
let result = self.execute_sbcd_val(dest_val, 0)?;
|
let result = self.execute_sbcd_val(dest_val, 0)?;
|
||||||
self.set_target_value(dest, result, Size::Byte, Used::Twice)?;
|
self.set_target_value(dest, result, Size::Byte, Used::Twice)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_neg(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_neg(&mut self, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let original = self.get_target_value(target, size, Used::Twice)?;
|
let original = self.get_target_value(target, size, Used::Twice)?;
|
||||||
let (result, overflow) = overflowing_sub_signed_sized(0, original, size);
|
let (result, overflow) = overflowing_sub_signed_sized(0, original, size);
|
||||||
let carry = result != 0;
|
let carry = result != 0;
|
||||||
|
@ -1218,7 +1241,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_negx(&mut self, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_negx(&mut self, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let extend = self.get_flag(Flags::Extend) as u32;
|
let extend = self.get_flag(Flags::Extend) as u32;
|
||||||
let (result1, carry1) = overflowing_sub_sized(0, dest_val, size);
|
let (result1, carry1) = overflowing_sub_sized(0, dest_val, size);
|
||||||
|
@ -1238,7 +1261,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_not(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_not(&mut self, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
||||||
value = get_value_sized(!value, size);
|
value = get_value_sized(!value, size);
|
||||||
self.set_target_value(target, value, size, Used::Twice)?;
|
self.set_target_value(target, value, size, Used::Twice)?;
|
||||||
|
@ -1246,7 +1269,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_or(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_or(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let result = get_value_sized(dest_val | src_val, size);
|
let result = get_value_sized(dest_val | src_val, size);
|
||||||
|
@ -1255,30 +1278,30 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_or_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
fn execute_or_to_ccr(&mut self, value: u8) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) | (value as u16)));
|
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) | (value as u16)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_or_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
fn execute_or_to_sr(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
self.set_sr(self.state.sr | value);
|
self.set_sr(self.state.sr | value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_pea(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_pea(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.get_target_address(target)?;
|
let value = self.get_target_address(target)?;
|
||||||
self.push_long(value)?;
|
self.push_long(value)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_reset(&mut self) -> Result<(), M68kError> {
|
fn execute_reset(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
// TODO this only resets external devices and not internal ones
|
// TODO this only resets external devices and not internal ones
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_rol(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_rol(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -1289,7 +1312,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_ror(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_ror(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -1300,7 +1323,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_roxl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_roxl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -1312,7 +1335,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_roxr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_roxr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
|
@ -1331,7 +1354,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_rte(&mut self) -> Result<(), M68kError> {
|
fn execute_rte(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
let sr = self.pop_word()?;
|
let sr = self.pop_word()?;
|
||||||
let addr = self.pop_long()?;
|
let addr = self.pop_long()?;
|
||||||
|
@ -1348,7 +1371,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_rtr(&mut self) -> Result<(), M68kError> {
|
fn execute_rtr(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let ccr = self.pop_word()?;
|
let ccr = self.pop_word()?;
|
||||||
let addr = self.pop_long()?;
|
let addr = self.pop_long()?;
|
||||||
self.set_sr((self.state.sr & 0xFF00) | (ccr & 0x00FF));
|
self.set_sr((self.state.sr & 0xFF00) | (ccr & 0x00FF));
|
||||||
|
@ -1359,7 +1382,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_rts(&mut self) -> Result<(), M68kError> {
|
fn execute_rts(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.debugger.stack_tracer.pop_return();
|
self.debugger.stack_tracer.pop_return();
|
||||||
let addr = self.pop_long()?;
|
let addr = self.pop_long()?;
|
||||||
if let Err(err) = self.set_pc(addr) {
|
if let Err(err) = self.set_pc(addr) {
|
||||||
|
@ -1369,7 +1392,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_scc(&mut self, cond: Condition, target: Target) -> Result<(), M68kError> {
|
fn execute_scc(&mut self, cond: Condition, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let condition_true = self.get_current_condition(cond);
|
let condition_true = self.get_current_condition(cond);
|
||||||
if condition_true {
|
if condition_true {
|
||||||
self.set_target_value(target, 0xFF, Size::Byte, Used::Once)?;
|
self.set_target_value(target, 0xFF, Size::Byte, Used::Once)?;
|
||||||
|
@ -1379,14 +1402,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_stop(&mut self, flags: u16) -> Result<(), M68kError> {
|
fn execute_stop(&mut self, flags: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.require_supervisor()?;
|
self.require_supervisor()?;
|
||||||
self.set_sr(flags);
|
self.set_sr(flags);
|
||||||
self.state.status = Status::Stopped;
|
self.state.status = Status::Stopped;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_sbcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError> {
|
fn execute_sbcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, Size::Byte, Used::Once)?;
|
let src_val = self.get_target_value(src, Size::Byte, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
||||||
let result = self.execute_sbcd_val(src_val, dest_val)?;
|
let result = self.execute_sbcd_val(src_val, dest_val)?;
|
||||||
|
@ -1394,7 +1417,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_sbcd_val(&mut self, src_val: u32, dest_val: u32) -> Result<u32, M68kError> {
|
fn execute_sbcd_val(&mut self, src_val: u32, dest_val: u32) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let extend_flag = self.get_flag(Flags::Extend) as u32;
|
let extend_flag = self.get_flag(Flags::Extend) as u32;
|
||||||
let src_parts = get_nibbles_from_byte(src_val);
|
let src_parts = get_nibbles_from_byte(src_val);
|
||||||
let dest_parts = get_nibbles_from_byte(dest_val);
|
let dest_parts = get_nibbles_from_byte(dest_val);
|
||||||
|
@ -1415,7 +1438,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_sub(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_sub(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let (result, carry) = overflowing_sub_sized(dest_val, src_val, size);
|
let (result, carry) = overflowing_sub_sized(dest_val, src_val, size);
|
||||||
|
@ -1426,7 +1449,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_suba(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError> {
|
fn execute_suba(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32;
|
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);
|
let dest_val = *self.get_a_reg_mut(dest);
|
||||||
let (result, _) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
let (result, _) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
||||||
|
@ -1434,7 +1457,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_subx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_subx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||||
let extend = self.get_flag(Flags::Extend) as u32;
|
let extend = self.get_flag(Flags::Extend) as u32;
|
||||||
|
@ -1455,14 +1478,14 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_swap(&mut self, reg: Register) -> Result<(), M68kError> {
|
fn execute_swap(&mut self, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.state.d_reg[reg as usize];
|
let value = self.state.d_reg[reg as usize];
|
||||||
self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16);
|
self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16);
|
||||||
self.set_logic_flags(self.state.d_reg[reg as usize], Size::Long);
|
self.set_logic_flags(self.state.d_reg[reg as usize], Size::Long);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_tas(&mut self, target: Target) -> Result<(), M68kError> {
|
fn execute_tas(&mut self, target: Target) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.get_target_value(target, Size::Byte, Used::Twice)?;
|
let value = self.get_target_value(target, Size::Byte, Used::Twice)?;
|
||||||
self.set_flag(Flags::Negative, (value & 0x80) != 0);
|
self.set_flag(Flags::Negative, (value & 0x80) != 0);
|
||||||
self.set_flag(Flags::Zero, value == 0);
|
self.set_flag(Flags::Zero, value == 0);
|
||||||
|
@ -1472,25 +1495,25 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_tst(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
fn execute_tst(&mut self, target: Target, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = self.get_target_value(target, size, Used::Once)?;
|
let value = self.get_target_value(target, size, Used::Once)?;
|
||||||
self.set_logic_flags(value, size);
|
self.set_logic_flags(value, size);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_trap(&mut self, number: u8) -> Result<(), M68kError> {
|
fn execute_trap(&mut self, number: u8) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.exception(32 + number, false)?;
|
self.exception(32 + number, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_trapv(&mut self) -> Result<(), M68kError> {
|
fn execute_trapv(&mut self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
if self.get_flag(Flags::Overflow) {
|
if self.get_flag(Flags::Overflow) {
|
||||||
self.exception(Exceptions::TrapvInstruction as u8, false)?;
|
self.exception(Exceptions::TrapvInstruction as u8, false)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_unlk(&mut self, reg: Register) -> Result<(), M68kError> {
|
fn execute_unlk(&mut self, reg: Register) -> Result<(), M68kError<Bus::Error>> {
|
||||||
let value = *self.get_a_reg_mut(reg);
|
let value = *self.get_a_reg_mut(reg);
|
||||||
*self.get_stack_pointer_mut() = value;
|
*self.get_stack_pointer_mut() = value;
|
||||||
let new_value = self.pop_long()?;
|
let new_value = self.pop_long()?;
|
||||||
|
@ -1499,20 +1522,20 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_unimplemented_a(&mut self, _: u16) -> Result<(), M68kError> {
|
fn execute_unimplemented_a(&mut self, _: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
self.exception(Exceptions::LineAEmulator as u8, false)?;
|
self.exception(Exceptions::LineAEmulator as u8, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_unimplemented_f(&mut self, _: u16) -> Result<(), M68kError> {
|
fn execute_unimplemented_f(&mut self, _: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.state.pc -= 2;
|
self.state.pc -= 2;
|
||||||
self.exception(Exceptions::LineFEmulator as u8, false)?;
|
self.exception(Exceptions::LineFEmulator as u8, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) fn get_target_value(&mut self, target: Target, size: Size, used: Used) -> Result<u32, M68kError> {
|
pub(super) fn get_target_value(&mut self, target: Target, size: Size, used: Used) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
match target {
|
match target {
|
||||||
Target::Immediate(value) => Ok(value),
|
Target::Immediate(value) => Ok(value),
|
||||||
Target::DirectDReg(reg) => Ok(get_value_sized(self.state.d_reg[reg as usize], size)),
|
Target::DirectDReg(reg) => Ok(get_value_sized(self.state.d_reg[reg as usize], size)),
|
||||||
|
@ -1552,7 +1575,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_target_value(&mut self, target: Target, value: u32, size: Size, used: Used) -> Result<(), M68kError> {
|
pub(super) fn set_target_value(&mut self, target: Target, value: u32, size: Size, used: Used) -> Result<(), M68kError<Bus::Error>> {
|
||||||
match target {
|
match target {
|
||||||
Target::DirectDReg(reg) => {
|
Target::DirectDReg(reg) => {
|
||||||
set_value_sized(&mut self.state.d_reg[reg as usize], value, size);
|
set_value_sized(&mut self.state.d_reg[reg as usize], value, size);
|
||||||
|
@ -1597,7 +1620,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_target_address(&mut self, target: Target) -> Result<u32, M68kError> {
|
fn get_target_address(&mut self, target: Target) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let addr = match target {
|
let addr = match target {
|
||||||
Target::IndirectAReg(reg) | Target::IndirectARegInc(reg) | Target::IndirectARegDec(reg) => *self.get_a_reg_mut(reg),
|
Target::IndirectAReg(reg) | Target::IndirectARegInc(reg) | Target::IndirectARegDec(reg) => *self.get_a_reg_mut(reg),
|
||||||
Target::IndirectRegOffset(base_reg, index_reg, displacement) => {
|
Target::IndirectRegOffset(base_reg, index_reg, displacement) => {
|
||||||
|
@ -1652,47 +1675,49 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
*reg_addr
|
*reg_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, M68kError> {
|
fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
self.cycle.memory.read_data_sized(self.port, self.is_supervisor(), addr, size)
|
let is_supervisor = self.is_supervisor();
|
||||||
|
self.cycle.memory.read_data_sized(&mut self.port, is_supervisor, addr, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
|
fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.cycle.memory.write_data_sized(self.port, self.is_supervisor(), addr, value, size)
|
let is_supervisor = self.is_supervisor();
|
||||||
|
self.cycle.memory.write_data_sized(&mut self.port, is_supervisor, addr, value, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_word(&mut self, value: u16) -> Result<(), M68kError> {
|
fn push_word(&mut self, value: u16) -> Result<(), M68kError<Bus::Error>> {
|
||||||
*self.get_stack_pointer_mut() -= 2;
|
*self.get_stack_pointer_mut() -= 2;
|
||||||
let addr = *self.get_stack_pointer_mut();
|
let addr = *self.get_stack_pointer_mut();
|
||||||
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?;
|
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?;
|
||||||
self.port.write_beu16(self.cycle.current_clock, addr as Address, value)?;
|
self.port.write_beu16(self.cycle.current_clock, addr as Address, value).map_err(|err| M68kError::BusError(err))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_word(&mut self) -> Result<u16, M68kError> {
|
fn pop_word(&mut self) -> Result<u16, M68kError<Bus::Error>> {
|
||||||
let addr = *self.get_stack_pointer_mut();
|
let addr = *self.get_stack_pointer_mut();
|
||||||
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?;
|
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?;
|
||||||
let value = self.port.read_beu16(self.cycle.current_clock, addr as Address)?;
|
let value = self.port.read_beu16(self.cycle.current_clock, addr as Address).map_err(|err| M68kError::BusError(err))?;
|
||||||
*self.get_stack_pointer_mut() += 2;
|
*self.get_stack_pointer_mut() += 2;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_long(&mut self, value: u32) -> Result<(), M68kError> {
|
fn push_long(&mut self, value: u32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
*self.get_stack_pointer_mut() -= 4;
|
*self.get_stack_pointer_mut() -= 4;
|
||||||
let addr = *self.get_stack_pointer_mut();
|
let addr = *self.get_stack_pointer_mut();
|
||||||
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?;
|
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?;
|
||||||
self.port.write_beu32(self.cycle.current_clock, addr as Address, value)?;
|
self.port.write_beu32(self.cycle.current_clock, addr as Address, value).map_err(|err| M68kError::BusError(err))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_long(&mut self) -> Result<u32, M68kError> {
|
fn pop_long(&mut self) -> Result<u32, M68kError<Bus::Error>> {
|
||||||
let addr = *self.get_stack_pointer_mut();
|
let addr = *self.get_stack_pointer_mut();
|
||||||
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?;
|
self.cycle.memory.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?;
|
||||||
let value = self.port.read_beu32(self.cycle.current_clock, addr as Address)?;
|
let value = self.port.read_beu32(self.cycle.current_clock, addr as Address).map_err(|err| M68kError::BusError(err))?;
|
||||||
*self.get_stack_pointer_mut() += 4;
|
*self.get_stack_pointer_mut() += 4;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_pc(&mut self, value: u32) -> Result<(), M68kError> {
|
fn set_pc(&mut self, value: u32) -> Result<(), M68kError<Bus::Error>> {
|
||||||
self.state.pc = value;
|
self.state.pc = value;
|
||||||
self.cycle.memory.start_request(self.is_supervisor(), self.state.pc, Size::Word, MemAccess::Read, MemType::Program, true)?;
|
self.cycle.memory.start_request(self.is_supervisor(), self.state.pc, Size::Word, MemAccess::Read, MemType::Program, true)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1769,7 +1794,7 @@ impl<'a> M68kCycleExecutor<'a> {
|
||||||
self.state.sr & (Flags:: Supervisor as u16) != 0
|
self.state.sr & (Flags:: Supervisor as u16) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn require_supervisor(&self) -> Result<(), M68kError> {
|
fn require_supervisor(&self) -> Result<(), M68kError<Bus::Error>> {
|
||||||
if self.is_supervisor() {
|
if self.is_supervisor() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
use femtos::Instant;
|
use femtos::Instant;
|
||||||
use emulator_hal::bus::{BusType, BusAccess};
|
use emulator_hal::bus::{BusAccess};
|
||||||
|
|
||||||
use moa_core::{Address, Addressable, BusPort};
|
use moa_core::{Error, Address, Addressable};
|
||||||
|
|
||||||
use crate::state::{M68k, M68kError, Exceptions};
|
use crate::state::{M68k, M68kError, Exceptions};
|
||||||
use crate::instructions::Size;
|
use crate::instructions::Size;
|
||||||
|
@ -76,7 +76,7 @@ impl Default for MemoryRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryRequest {
|
impl MemoryRequest {
|
||||||
pub(crate) fn instruction(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
|
pub(crate) fn instruction<BusError>(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError<BusError>> {
|
||||||
self.i_n_bit = false;
|
self.i_n_bit = false;
|
||||||
self.code = FunctionCode::program(is_supervisor);
|
self.code = FunctionCode::program(is_supervisor);
|
||||||
self.access = MemAccess::Read;
|
self.access = MemAccess::Read;
|
||||||
|
@ -101,6 +101,8 @@ impl MemoryRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pub type M68kAddress = (FunctionCode, u32);
|
||||||
|
pub type M68kAddress = u64;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct InstructionRequest {
|
pub struct InstructionRequest {
|
||||||
|
@ -110,7 +112,6 @@ pub struct InstructionRequest {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct M68kBusPort {
|
pub struct M68kBusPort {
|
||||||
//pub port: BusPort,
|
|
||||||
pub request: MemoryRequest,
|
pub request: MemoryRequest,
|
||||||
pub cycle_start_clock: Instant,
|
pub cycle_start_clock: Instant,
|
||||||
pub current_clock: Instant,
|
pub current_clock: Instant,
|
||||||
|
@ -122,9 +123,8 @@ impl M68k {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for M68kBusPort {
|
impl Default for M68kBusPort {
|
||||||
fn default(/* port: BusPort */) -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
//port,
|
|
||||||
request: Default::default(),
|
request: Default::default(),
|
||||||
cycle_start_clock: Instant::START,
|
cycle_start_clock: Instant::START,
|
||||||
current_clock: Instant::START,
|
current_clock: Instant::START,
|
||||||
|
@ -141,35 +141,47 @@ impl M68kBusPort {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_data_sized(&mut self, port: &mut BusPort, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, M68kError> {
|
pub(crate) fn read_data_sized<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, M68kError<BusError>>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
|
{
|
||||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
|
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
|
||||||
Ok(match size {
|
Ok(match size {
|
||||||
Size::Byte => port.read_u8(self.current_clock, addr).map(|value| value as u32),
|
Size::Byte => port.read_u8(self.current_clock, addr).map(|value| value as u32),
|
||||||
Size::Word => port.read_beu16(self.current_clock, addr).map(|value| value as u32),
|
Size::Word => port.read_beu16(self.current_clock, addr).map(|value| value as u32),
|
||||||
Size::Long => port.read_beu32(self.current_clock, addr),
|
Size::Long => port.read_beu32(self.current_clock, addr),
|
||||||
}?)
|
}.map_err(|err| M68kError::BusError(err))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_data_sized(&mut self, port: &mut BusPort, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
|
pub(crate) fn write_data_sized<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), M68kError<BusError>>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
|
{
|
||||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
|
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
|
||||||
Ok(match size {
|
Ok(match size {
|
||||||
Size::Byte => port.write_u8(self.current_clock, addr, value as u8),
|
Size::Byte => port.write_u8(self.current_clock, addr, value as u8),
|
||||||
Size::Word => port.write_beu16(self.current_clock, addr, value as u16),
|
Size::Word => port.write_beu16(self.current_clock, addr, value as u16),
|
||||||
Size::Long => port.write_beu32(self.current_clock, addr, value),
|
Size::Long => port.write_beu32(self.current_clock, addr, value),
|
||||||
}?)
|
}.map_err(|err| M68kError::BusError(err))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_instruction_word(&mut self, port: &mut BusPort, is_supervisor: bool, addr: u32) -> Result<u16, M68kError> {
|
pub(crate) fn read_instruction_word<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u16, M68kError<BusError>>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
|
{
|
||||||
self.request.instruction(is_supervisor, addr)?;
|
self.request.instruction(is_supervisor, addr)?;
|
||||||
Ok(port.read_beu16(self.current_clock, addr as Address)?)
|
Ok(port.read_beu16(self.current_clock, addr as Address).map_err(|err| M68kError::BusError(err))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_instruction_long(&mut self, port: &mut BusPort, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
|
pub(crate) fn read_instruction_long<Bus, BusError>(&mut self, port: &mut Bus, is_supervisor: bool, addr: u32) -> Result<u32, M68kError<BusError>>
|
||||||
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
|
{
|
||||||
self.request.instruction(is_supervisor, addr)?;
|
self.request.instruction(is_supervisor, addr)?;
|
||||||
Ok(port.read_beu32(self.current_clock, addr as Address)?)
|
Ok(port.read_beu32(self.current_clock, addr as Address).map_err(|err| M68kError::BusError(err))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start_request(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, M68kError> {
|
pub(crate) fn start_request<BusError>(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, M68kError<BusError>> {
|
||||||
self.request.i_n_bit = i_n_bit;
|
self.request.i_n_bit = i_n_bit;
|
||||||
self.request.code = match mtype {
|
self.request.code = match mtype {
|
||||||
MemType::Program => FunctionCode::program(is_supervisor),
|
MemType::Program => FunctionCode::program(is_supervisor),
|
||||||
|
@ -186,12 +198,16 @@ impl M68kBusPort {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn dump_memory(&mut self, port: &mut BusPort, addr: u32, length: usize) {
|
pub(crate) fn dump_memory<Bus, BusError>(&mut self, port: &mut Bus, addr: u32, length: usize)
|
||||||
port.dump_memory(self.current_clock, addr as Address, length as u64);
|
where
|
||||||
|
Bus: BusAccess<M68kAddress, Instant, Error = BusError>,
|
||||||
|
{
|
||||||
|
// TODO temporarily disabled
|
||||||
|
//port.dump_memory(self.current_clock, addr as Address, length as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_address(addr: u32) -> Result<u32, M68kError> {
|
fn validate_address<BusError>(addr: u32) -> Result<u32, M68kError<BusError>> {
|
||||||
if addr & 0x1 == 0 {
|
if addr & 0x1 == 0 {
|
||||||
Ok(addr)
|
Ok(addr)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::fmt::Display;
|
||||||
use femtos::{Instant, Frequency};
|
use femtos::{Instant, Frequency};
|
||||||
|
|
||||||
use moa_core::{Address, Bus, BusPort};
|
use moa_core::{Address, Bus, BusPort};
|
||||||
|
@ -178,7 +179,7 @@ pub struct M68kState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, thiserror::Error)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
pub enum M68kError {
|
pub enum M68kError<BusError> {
|
||||||
#[error("cpu halted")]
|
#[error("cpu halted")]
|
||||||
Halted,
|
Halted,
|
||||||
#[error("processor exception {0:?}")]
|
#[error("processor exception {0:?}")]
|
||||||
|
@ -189,6 +190,8 @@ pub enum M68kError {
|
||||||
Breakpoint,
|
Breakpoint,
|
||||||
#[error("invalid instruction target, direct value used as a pointer: {0:?}")]
|
#[error("invalid instruction target, direct value used as a pointer: {0:?}")]
|
||||||
InvalidTarget(Target),
|
InvalidTarget(Target),
|
||||||
|
#[error("bus error")]
|
||||||
|
BusError(BusError),
|
||||||
#[error("error: {0}")]
|
#[error("error: {0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ pub struct M68kInstructionTiming {
|
||||||
pub cputype: M68kType,
|
pub cputype: M68kType,
|
||||||
pub bus_size: Size,
|
pub bus_size: Size,
|
||||||
|
|
||||||
|
pub branched: bool,
|
||||||
|
pub reps: u16,
|
||||||
|
|
||||||
pub accesses: u8,
|
pub accesses: u8,
|
||||||
pub internal: u8,
|
pub internal: u8,
|
||||||
pub on_branch: u8,
|
pub on_branch: u8,
|
||||||
|
@ -22,6 +25,9 @@ impl M68kInstructionTiming {
|
||||||
cputype,
|
cputype,
|
||||||
bus_size,
|
bus_size,
|
||||||
|
|
||||||
|
branched: false,
|
||||||
|
reps: 0,
|
||||||
|
|
||||||
accesses: 0,
|
accesses: 0,
|
||||||
internal: 0,
|
internal: 0,
|
||||||
on_branch: 0,
|
on_branch: 0,
|
||||||
|
@ -338,12 +344,27 @@ impl M68kInstructionTiming {
|
||||||
self.add_internal(4)
|
self.add_internal(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_clocks(&self, branched: bool, reps: u16) -> ClockCycles {
|
pub fn performed_reset(&mut self) {
|
||||||
|
self.internal = 0;
|
||||||
|
self.accesses = 4;
|
||||||
|
self.branched = false;
|
||||||
|
self.reps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn increase_reps(&mut self, reps: u16) {
|
||||||
|
self.reps += reps;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn branch_taken(&mut self) {
|
||||||
|
self.branched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn calculate_clocks(&self) -> ClockCycles {
|
||||||
//println!("{:?}", self);
|
//println!("{:?}", self);
|
||||||
(self.accesses as ClockCycles * 4)
|
(self.accesses as ClockCycles * 4)
|
||||||
+ self.internal as ClockCycles
|
+ self.internal as ClockCycles
|
||||||
+ (if branched { self.on_branch as ClockCycles } else { 0 })
|
+ (if self.branched { self.on_branch as ClockCycles } else { 0 })
|
||||||
+ self.per_rep as ClockCycles * reps
|
+ self.per_rep as ClockCycles * self.reps
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -6,18 +6,12 @@ use moa_core::{Address, Addressable};
|
||||||
use crate::state::Z80Error;
|
use crate::state::Z80Error;
|
||||||
use crate::instructions::{Direction, Condition, Register, RegisterPair, IndexRegister, IndexRegisterHalf, SpecialRegister, InterruptMode, Target, LoadTarget, UndocumentedCopy, Instruction};
|
use crate::instructions::{Direction, Condition, Register, RegisterPair, IndexRegister, IndexRegisterHalf, SpecialRegister, InterruptMode, Target, LoadTarget, UndocumentedCopy, Instruction};
|
||||||
|
|
||||||
use emulator_hal::bus::{BusType, BusAccess};
|
use emulator_hal::bus::{BusAccess};
|
||||||
|
|
||||||
struct Z80Bus;
|
struct Z80Bus;
|
||||||
|
|
||||||
type Z80Address = (bool, u16);
|
type Z80Address = (bool, u16);
|
||||||
|
|
||||||
impl BusType for Z80Bus {
|
|
||||||
//type Address = (bool, u16);
|
|
||||||
type Error = Z80Error;
|
|
||||||
type Instant = Instant;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Z80Decoder {
|
pub struct Z80Decoder {
|
||||||
pub clock: Instant,
|
pub clock: Instant,
|
||||||
|
|
|
@ -1,129 +1,129 @@
|
||||||
Last run on 2022-09-18 at commit 94d3e1d3894e6588ff6daa55f0ba82473b1e74c7
|
Last run on 2024-03-08 at commit b4a35641e4d52349f1d392f749da2e4af561a5e0
|
||||||
|
|
||||||
ABCD.json completed: 7993 passed, 72 FAILED
|
ABCD.json.gz completed: 7993 passed, 72 FAILED
|
||||||
ADD.b.json completed, all passed!
|
ADD.b.json.gz completed, all passed!
|
||||||
ADD.l.json completed: 7736 passed, 329 FAILED
|
ADD.l.json.gz completed: 7736 passed, 329 FAILED
|
||||||
ADD.w.json completed: 7712 passed, 353 FAILED
|
ADD.w.json.gz completed: 7712 passed, 353 FAILED
|
||||||
ADDA.l.json completed, all passed!
|
ADDA.l.json.gz completed, all passed!
|
||||||
ADDA.w.json completed, all passed!
|
ADDA.w.json.gz completed, all passed!
|
||||||
ADDX.b.json completed, all passed!
|
ADDX.b.json.gz completed, all passed!
|
||||||
ADDX.l.json completed: 5472 passed, 2593 FAILED
|
ADDX.l.json.gz completed: 5472 passed, 2593 FAILED
|
||||||
ADDX.w.json completed, all passed!
|
ADDX.w.json.gz completed, all passed!
|
||||||
AND.b.json completed, all passed!
|
AND.b.json.gz completed, all passed!
|
||||||
AND.l.json completed: 7779 passed, 286 FAILED
|
AND.l.json.gz completed: 7779 passed, 286 FAILED
|
||||||
AND.w.json completed: 7764 passed, 301 FAILED
|
AND.w.json.gz completed: 7764 passed, 301 FAILED
|
||||||
ANDItoCCR.json completed, all passed!
|
ANDItoCCR.json.gz completed, all passed!
|
||||||
ANDItoSR.json completed, all passed!
|
ANDItoSR.json.gz completed, all passed!
|
||||||
ASL.b.json completed: 7238 passed, 827 FAILED
|
ASL.b.json.gz completed: 8063 passed, 2 FAILED
|
||||||
ASL.l.json completed: 6471 passed, 1594 FAILED
|
ASL.l.json.gz completed, all passed!
|
||||||
ASL.w.json completed: 7053 passed, 1012 FAILED
|
ASL.w.json.gz completed: 7896 passed, 169 FAILED
|
||||||
ASR.b.json completed: 7547 passed, 518 FAILED
|
ASR.b.json.gz completed: 7783 passed, 282 FAILED
|
||||||
ASR.l.json completed: 7092 passed, 973 FAILED
|
ASR.l.json.gz completed: 8029 passed, 36 FAILED
|
||||||
ASR.w.json completed: 7513 passed, 552 FAILED
|
ASR.w.json.gz completed: 7891 passed, 174 FAILED
|
||||||
BCHG.json completed, all passed!
|
BCHG.json.gz completed, all passed!
|
||||||
BCLR.json completed, all passed!
|
BCLR.json.gz completed, all passed!
|
||||||
BSET.json completed, all passed!
|
BSET.json.gz completed, all passed!
|
||||||
BSR.json completed, all passed!
|
BSR.json.gz completed, all passed!
|
||||||
BTST.json completed: 8052 passed, 13 FAILED
|
BTST.json.gz completed: 8052 passed, 13 FAILED
|
||||||
Bcc.json completed, all passed!
|
Bcc.json.gz completed, all passed!
|
||||||
CHK.json completed: 7744 passed, 321 FAILED
|
CHK.json.gz completed: 7744 passed, 321 FAILED
|
||||||
CLR.b.json completed, all passed!
|
CLR.b.json.gz completed, all passed!
|
||||||
CLR.l.json completed: 7472 passed, 593 FAILED
|
CLR.l.json.gz completed: 7472 passed, 593 FAILED
|
||||||
CLR.w.json completed: 7465 passed, 600 FAILED
|
CLR.w.json.gz completed: 7465 passed, 600 FAILED
|
||||||
CMP.b.json completed, all passed!
|
CMP.b.json.gz completed, all passed!
|
||||||
CMP.l.json completed, all passed!
|
CMP.l.json.gz completed, all passed!
|
||||||
CMP.w.json completed, all passed!
|
CMP.w.json.gz completed, all passed!
|
||||||
CMPA.l.json completed, all passed!
|
CMPA.l.json.gz completed, all passed!
|
||||||
CMPA.w.json completed, all passed!
|
CMPA.w.json.gz completed, all passed!
|
||||||
DBcc.json completed, all passed!
|
DBcc.json.gz completed, all passed!
|
||||||
DIVS.json completed, all passed!
|
DIVS.json.gz completed, all passed!
|
||||||
DIVU.json completed: 8064 passed, 1 FAILED
|
DIVU.json.gz completed: 8064 passed, 1 FAILED
|
||||||
EOR.b.json completed, all passed!
|
EOR.b.json.gz completed, all passed!
|
||||||
EOR.l.json completed: 7519 passed, 546 FAILED
|
EOR.l.json.gz completed: 7519 passed, 546 FAILED
|
||||||
EOR.w.json completed: 7525 passed, 540 FAILED
|
EOR.w.json.gz completed: 7525 passed, 540 FAILED
|
||||||
EORItoCCR.json completed, all passed!
|
EORItoCCR.json.gz completed, all passed!
|
||||||
EORItoSR.json completed, all passed!
|
EORItoSR.json.gz completed, all passed!
|
||||||
EXG.json completed, all passed!
|
EXG.json.gz completed, all passed!
|
||||||
EXT.l.json completed, all passed!
|
EXT.l.json.gz completed, all passed!
|
||||||
EXT.w.json completed, all passed!
|
EXT.w.json.gz completed, all passed!
|
||||||
JMP.json completed, all passed!
|
JMP.json.gz completed, all passed!
|
||||||
JSR.json completed, all passed!
|
JSR.json.gz completed, all passed!
|
||||||
LEA.json completed, all passed!
|
LEA.json.gz completed, all passed!
|
||||||
LINK.json completed, all passed!
|
LINK.json.gz completed, all passed!
|
||||||
LSL.b.json completed: 7809 passed, 256 FAILED
|
LSL.b.json.gz completed, all passed!
|
||||||
LSL.l.json completed: 7056 passed, 1009 FAILED
|
LSL.l.json.gz completed, all passed!
|
||||||
LSL.w.json completed: 7523 passed, 542 FAILED
|
LSL.w.json.gz completed: 7910 passed, 155 FAILED
|
||||||
LSR.b.json completed: 7817 passed, 248 FAILED
|
LSR.b.json.gz completed, all passed!
|
||||||
LSR.l.json completed: 7072 passed, 993 FAILED
|
LSR.l.json.gz completed, all passed!
|
||||||
LSR.w.json completed: 7541 passed, 524 FAILED
|
LSR.w.json.gz completed: 7909 passed, 156 FAILED
|
||||||
MOVE.b.json completed, all passed!
|
MOVE.b.json.gz completed, all passed!
|
||||||
MOVE.l.json completed: 5827 passed, 2238 FAILED
|
MOVE.l.json.gz completed: 5827 passed, 2238 FAILED
|
||||||
MOVE.q.json completed, all passed!
|
MOVE.q.json.gz completed, all passed!
|
||||||
MOVE.w.json completed: 5855 passed, 2210 FAILED
|
MOVE.w.json.gz completed: 5855 passed, 2210 FAILED
|
||||||
MOVEA.l.json completed, all passed!
|
MOVEA.l.json.gz completed, all passed!
|
||||||
MOVEA.w.json completed, all passed!
|
MOVEA.w.json.gz completed, all passed!
|
||||||
MOVEM.l.json completed: 6035 passed, 2030 FAILED
|
MOVEM.l.json.gz completed: 6035 passed, 2030 FAILED
|
||||||
MOVEM.w.json completed: 6431 passed, 1634 FAILED
|
MOVEM.w.json.gz completed: 6431 passed, 1634 FAILED
|
||||||
MOVEP.l.json completed: 4036 passed, 4029 FAILED
|
MOVEP.l.json.gz completed: 4036 passed, 4029 FAILED
|
||||||
MOVEP.w.json completed: 4046 passed, 4019 FAILED
|
MOVEP.w.json.gz completed: 4046 passed, 4019 FAILED
|
||||||
MOVEfromSR.json completed: 6896 passed, 1169 FAILED
|
MOVEfromSR.json.gz completed: 6896 passed, 1169 FAILED
|
||||||
MOVEfromUSP.json completed, all passed!
|
MOVEfromUSP.json.gz completed, all passed!
|
||||||
MOVEtoCCR.json completed, all passed!
|
MOVEtoCCR.json.gz completed, all passed!
|
||||||
MOVEtoSR.json completed, all passed!
|
MOVEtoSR.json.gz completed, all passed!
|
||||||
MOVEtoUSP.json completed, all passed!
|
MOVEtoUSP.json.gz completed, all passed!
|
||||||
MULS.json completed, all passed!
|
MULS.json.gz completed, all passed!
|
||||||
MULU.json completed, all passed!
|
MULU.json.gz completed, all passed!
|
||||||
NBCD.json completed: 8037 passed, 28 FAILED
|
NBCD.json.gz completed: 8037 passed, 28 FAILED
|
||||||
NEG.b.json completed, all passed!
|
NEG.b.json.gz completed, all passed!
|
||||||
NEG.l.json completed: 7552 passed, 513 FAILED
|
NEG.l.json.gz completed: 7552 passed, 513 FAILED
|
||||||
NEG.w.json completed: 7531 passed, 534 FAILED
|
NEG.w.json.gz completed: 7531 passed, 534 FAILED
|
||||||
NEGX.b.json completed, all passed!
|
NEGX.b.json.gz completed, all passed!
|
||||||
NEGX.l.json completed: 7520 passed, 545 FAILED
|
NEGX.l.json.gz completed: 7520 passed, 545 FAILED
|
||||||
NEGX.w.json completed: 7510 passed, 555 FAILED
|
NEGX.w.json.gz completed: 7510 passed, 555 FAILED
|
||||||
NOP.json completed, all passed!
|
NOP.json.gz completed, all passed!
|
||||||
NOT.b.json completed, all passed!
|
NOT.b.json.gz completed, all passed!
|
||||||
NOT.l.json completed: 7512 passed, 553 FAILED
|
NOT.l.json.gz completed: 7512 passed, 553 FAILED
|
||||||
NOT.w.json completed: 7530 passed, 535 FAILED
|
NOT.w.json.gz completed: 7530 passed, 535 FAILED
|
||||||
OR.b.json completed, all passed!
|
OR.b.json.gz completed, all passed!
|
||||||
OR.l.json completed: 7756 passed, 309 FAILED
|
OR.l.json.gz completed: 7756 passed, 309 FAILED
|
||||||
OR.w.json completed: 7765 passed, 300 FAILED
|
OR.w.json.gz completed: 7765 passed, 300 FAILED
|
||||||
ORItoCCR.json completed, all passed!
|
ORItoCCR.json.gz completed, all passed!
|
||||||
ORItoSR.json completed, all passed!
|
ORItoSR.json.gz completed, all passed!
|
||||||
PEA.json completed, all passed!
|
PEA.json.gz completed, all passed!
|
||||||
RESET.json completed, all passed!
|
RESET.json.gz completed, all passed!
|
||||||
ROL.b.json completed, all passed!
|
ROL.b.json.gz completed, all passed!
|
||||||
ROL.l.json completed, all passed!
|
ROL.l.json.gz completed, all passed!
|
||||||
ROL.w.json completed: 7882 passed, 183 FAILED
|
ROL.w.json.gz completed: 7898 passed, 167 FAILED
|
||||||
ROR.b.json completed, all passed!
|
ROR.b.json.gz completed, all passed!
|
||||||
ROR.l.json completed, all passed!
|
ROR.l.json.gz completed, all passed!
|
||||||
ROR.w.json completed: 7907 passed, 158 FAILED
|
ROR.w.json.gz completed: 7932 passed, 133 FAILED
|
||||||
ROXL.b.json completed: 8039 passed, 26 FAILED
|
ROXL.b.json.gz completed: 8032 passed, 33 FAILED
|
||||||
ROXL.l.json completed: 8029 passed, 36 FAILED
|
ROXL.l.json.gz completed: 8029 passed, 36 FAILED
|
||||||
ROXL.w.json completed: 7892 passed, 173 FAILED
|
ROXL.w.json.gz completed: 7890 passed, 175 FAILED
|
||||||
ROXR.b.json completed: 8037 passed, 28 FAILED
|
ROXR.b.json.gz completed: 8027 passed, 38 FAILED
|
||||||
ROXR.l.json completed: 8022 passed, 43 FAILED
|
ROXR.l.json.gz completed: 8039 passed, 26 FAILED
|
||||||
ROXR.w.json completed: 7880 passed, 185 FAILED
|
ROXR.w.json.gz completed: 7880 passed, 185 FAILED
|
||||||
RTE.json completed, all passed!
|
RTE.json.gz completed, all passed!
|
||||||
RTR.json completed, all passed!
|
RTR.json.gz completed, all passed!
|
||||||
RTS.json completed, all passed!
|
RTS.json.gz completed, all passed!
|
||||||
SBCD.json completed: 6809 passed, 1256 FAILED
|
SBCD.json.gz completed: 6809 passed, 1256 FAILED
|
||||||
SUB.b.json completed, all passed!
|
SUB.b.json.gz completed, all passed!
|
||||||
SUB.l.json completed: 7747 passed, 318 FAILED
|
SUB.l.json.gz completed: 7747 passed, 318 FAILED
|
||||||
SUB.w.json completed: 7716 passed, 349 FAILED
|
SUB.w.json.gz completed: 7716 passed, 349 FAILED
|
||||||
SUBA.l.json completed, all passed!
|
SUBA.l.json.gz completed, all passed!
|
||||||
SUBA.w.json completed, all passed!
|
SUBA.w.json.gz completed, all passed!
|
||||||
SUBX.b.json completed, all passed!
|
SUBX.b.json.gz completed, all passed!
|
||||||
SUBX.l.json completed: 5481 passed, 2584 FAILED
|
SUBX.l.json.gz completed: 5481 passed, 2584 FAILED
|
||||||
SUBX.w.json completed, all passed!
|
SUBX.w.json.gz completed, all passed!
|
||||||
SWAP.json completed, all passed!
|
SWAP.json.gz completed, all passed!
|
||||||
Scc.json completed, all passed!
|
Scc.json.gz completed, all passed!
|
||||||
TAS.json completed, all passed!
|
TAS.json.gz completed, all passed!
|
||||||
TRAP.json completed, all passed!
|
TRAP.json.gz completed, all passed!
|
||||||
TRAPV.json completed, all passed!
|
TRAPV.json.gz completed, all passed!
|
||||||
TST.b.json completed, all passed!
|
TST.b.json.gz completed, all passed!
|
||||||
TST.l.json completed, all passed!
|
TST.l.json.gz completed, all passed!
|
||||||
TST.w.json completed, all passed!
|
TST.w.json.gz completed, all passed!
|
||||||
UNLINK.json completed, all passed!
|
UNLINK.json.gz completed, all passed!
|
||||||
|
|
||||||
passed: 957924, failed: 42136, total 96%
|
passed: 966037, failed: 34023, total 97%
|
||||||
completed in 24m 47s
|
completed in 14m 25s
|
||||||
|
|
|
@ -150,7 +150,7 @@ fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, Syst
|
||||||
} else {
|
} else {
|
||||||
BusPort::new(0, 32, 32, system.bus.clone())
|
BusPort::new(0, 32, 32, system.bus.clone())
|
||||||
};
|
};
|
||||||
let mut cpu = M68k::new(cputype, Frequency::from_mhz(10), port);
|
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10), system.bus.clone(), 0);
|
||||||
cpu.state.status = Status::Running;
|
cpu.state.status = Status::Running;
|
||||||
|
|
||||||
load_state(&mut cpu, &mut system, state)?;
|
load_state(&mut cpu, &mut system, state)?;
|
||||||
|
@ -226,7 +226,7 @@ fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(),
|
||||||
assert_value(cpu.state.sr, expected.sr, "sr")?;
|
assert_value(cpu.state.sr, expected.sr, "sr")?;
|
||||||
assert_value(cpu.state.pc, expected.pc, "pc")?;
|
assert_value(cpu.state.pc, expected.pc, "pc")?;
|
||||||
|
|
||||||
let addr_mask = cpu.port.port.address_mask();
|
let addr_mask = cpu.port.address_mask();
|
||||||
|
|
||||||
// Load instructions into memory
|
// Load instructions into memory
|
||||||
for (i, ins) in expected.prefetch.iter().enumerate() {
|
for (i, ins) in expected.prefetch.iter().enumerate() {
|
||||||
|
@ -246,7 +246,7 @@ fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(),
|
||||||
|
|
||||||
fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> {
|
fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> {
|
||||||
let clock_elapsed = cpu.step(&system)?;
|
let clock_elapsed = cpu.step(&system)?;
|
||||||
let cycles = clock_elapsed / cpu.frequency.period_duration();
|
let cycles = clock_elapsed / cpu.info.frequency.period_duration();
|
||||||
|
|
||||||
assert_state(&cpu, &system, &case.final_state)?;
|
assert_state(&cpu, &system, &case.final_state)?;
|
||||||
|
|
||||||
|
@ -269,8 +269,8 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
|
||||||
if args.debug {
|
if args.debug {
|
||||||
case.dump();
|
case.dump();
|
||||||
println!("");
|
println!("");
|
||||||
initial_cpu.dump_state();
|
//initial_cpu.dump_state();
|
||||||
cpu.dump_state();
|
//cpu.dump_state();
|
||||||
}
|
}
|
||||||
println!("FAILED: {:?}", err);
|
println!("FAILED: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
6
todo.txt
6
todo.txt
|
@ -2,10 +2,16 @@
|
||||||
* I want to push System, and BusPort into only the step function
|
* I want to push System, and BusPort into only the step function
|
||||||
* first I need to make Decoder take &mut Addressable, and still function like it does
|
* first I need to make Decoder take &mut Addressable, and still function like it does
|
||||||
* next I need to make Executor only access through a &mut Addressable
|
* next I need to make Executor only access through a &mut Addressable
|
||||||
|
|
||||||
|
* move the BusPort breakup code to m68k
|
||||||
|
* implement BusAccess for BusPort
|
||||||
* move the interrupt controller logic to the step() function only, and have a customish interrupt interface into the sim
|
* move the interrupt controller logic to the step() function only, and have a customish interrupt interface into the sim
|
||||||
* move the impls for Step, Transmutable, etc into a moa.rs file or something
|
* move the impls for Step, Transmutable, etc into a moa.rs file or something
|
||||||
* the remaining code should really use Addressable, and then we can swap it for BusAccess
|
* the remaining code should really use Addressable, and then we can swap it for BusAccess
|
||||||
|
|
||||||
|
* could you use the m68k cpu status enum for interrupts, and start handling the interrupt in the next step? but that will affect tests and behaviour if it takes two steps
|
||||||
|
to get to the same point...
|
||||||
|
|
||||||
* the idea would be, instead of argument drilling, you create an object that is short lived, that lasts one instruction, or possibly even parts of one instruction, and
|
* the idea would be, instead of argument drilling, you create an object that is short lived, that lasts one instruction, or possibly even parts of one instruction, and
|
||||||
it has some references instead of "moving" data (or if you move, you move and move out without cloning), such that you can bundle everything up, call a method on the
|
it has some references instead of "moving" data (or if you move, you move and move out without cloning), such that you can bundle everything up, call a method on the
|
||||||
bundle, with the execution context and state all part of or reference by the bundle, all instructions would be implemented on the bundle and not the state alone, and
|
bundle, with the execution context and state all part of or reference by the bundle, all instructions would be implemented on the bundle and not the state alone, and
|
||||||
|
|
Loading…
Reference in New Issue