Added custom error type
This commit is contained in:
parent
55efc4f406
commit
e13c172364
|
@ -1,7 +1,7 @@
|
|||
|
||||
use moa_core::{Error, Address, Addressable};
|
||||
use moa_core::{Address, Addressable};
|
||||
|
||||
use crate::state::{M68kType, Exceptions};
|
||||
use crate::state::{M68kType, M68kError, Exceptions};
|
||||
use crate::memory::M68kBusPort;
|
||||
use crate::instructions::{
|
||||
Size,
|
||||
|
@ -66,13 +66,13 @@ impl M68kDecoder {
|
|||
self.end = start;
|
||||
}
|
||||
|
||||
pub fn decode_at(&mut self, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), Error> {
|
||||
pub fn decode_at(&mut self, memory: &mut M68kBusPort, is_supervisor: bool, start: u32) -> Result<(), M68kError> {
|
||||
self.init(is_supervisor, start);
|
||||
self.instruction = self.decode_next(memory)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_next(&mut self, memory: &mut M68kBusPort) -> Result<Instruction, Error> {
|
||||
pub fn decode_next(&mut self, memory: &mut M68kBusPort) -> Result<Instruction, M68kError> {
|
||||
let ins = self.read_instruction_word(memory)?;
|
||||
self.instruction_word = ins;
|
||||
|
||||
|
@ -93,12 +93,12 @@ impl M68kDecoder {
|
|||
OPCG_ADD => self.decode_group_add(memory, ins),
|
||||
OPCG_SHIFT => self.decode_group_shift(memory, ins),
|
||||
OPCG_FLINE => Ok(Instruction::UnimplementedF(ins)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_bit_ops(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_bit_ops(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let optype = (ins & 0x0F00) >> 8;
|
||||
|
||||
if (ins & 0x13F) == 0x03C {
|
||||
|
@ -109,7 +109,7 @@ impl M68kDecoder {
|
|||
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
|
||||
0b0010 => Ok(Instruction::ANDtoCCR(data as u8)),
|
||||
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
},
|
||||
0b01 => {
|
||||
|
@ -118,10 +118,10 @@ impl M68kDecoder {
|
|||
0b0000 => Ok(Instruction::ORtoSR(data)),
|
||||
0b0010 => Ok(Instruction::ANDtoSR(data)),
|
||||
0b1010 => Ok(Instruction::EORtoSR(data)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
},
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else if (ins & 0x138) == 0x108 {
|
||||
let dreg = get_high_reg(ins);
|
||||
|
@ -148,7 +148,7 @@ impl M68kDecoder {
|
|||
0b01 => Ok(Instruction::BCHG(bitnum, target, size)),
|
||||
0b10 => Ok(Instruction::BCLR(bitnum, target, size)),
|
||||
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else {
|
||||
let size = get_size(ins);
|
||||
|
@ -156,7 +156,7 @@ impl M68kDecoder {
|
|||
Some(Size::Byte) => self.read_instruction_word(memory)? as u32 & 0xFF,
|
||||
Some(Size::Word) => self.read_instruction_word(memory)? as u32,
|
||||
Some(Size::Long) => self.read_instruction_long(memory)?,
|
||||
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
let target = self.decode_lower_effective_address(memory, ins, size)?;
|
||||
|
||||
|
@ -167,20 +167,20 @@ impl M68kDecoder {
|
|||
0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())),
|
||||
0b1010 => Ok(Instruction::EOR(Target::Immediate(data), target, size.unwrap())),
|
||||
0b1100 => Ok(Instruction::CMP(Target::Immediate(data), target, size.unwrap())),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_move_byte(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_move_byte(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let src = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?;
|
||||
let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Byte))?;
|
||||
Ok(Instruction::MOVE(src, dest, Size::Byte))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_move_long(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_move_long(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let src = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?;
|
||||
let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Long))?;
|
||||
if let Target::DirectAReg(reg) = dest {
|
||||
|
@ -191,7 +191,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_move_word(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_move_word(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let src = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
|
||||
let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Word))?;
|
||||
if let Target::DirectAReg(reg) = dest {
|
||||
|
@ -202,7 +202,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_misc(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_misc(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let ins_0f00 = ins & 0xF00;
|
||||
let ins_00f0 = ins & 0x0F0;
|
||||
|
||||
|
@ -213,7 +213,7 @@ impl M68kDecoder {
|
|||
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
||||
// On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction
|
||||
Some(Size::Long) => Size::Word,
|
||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
|
||||
let reg = get_high_reg(ins);
|
||||
|
@ -253,7 +253,7 @@ impl M68kDecoder {
|
|||
match get_size(ins) {
|
||||
Some(size) => Ok(Instruction::CLR(target, size)),
|
||||
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
|
||||
None => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
None => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
},
|
||||
0b100 => {
|
||||
|
@ -268,7 +268,7 @@ impl M68kDecoder {
|
|||
None => Ok(Instruction::MOVEtoSR(target)),
|
||||
}
|
||||
},
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else if ins_0f00 == 0x800 || ins_0f00 == 0x900 {
|
||||
let opmode = (ins & 0x01C0) >> 6;
|
||||
|
@ -301,7 +301,7 @@ impl M68kDecoder {
|
|||
(0b111, 0b000) => {
|
||||
Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long))
|
||||
},
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else if ins_0f00 == 0xA00 {
|
||||
if (ins & 0x0FF) == 0xFC {
|
||||
|
@ -360,20 +360,20 @@ impl M68kDecoder {
|
|||
};
|
||||
let creg = match ins2 & 0xFFF {
|
||||
0x801 => ControlRegister::VBR,
|
||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
Ok(Instruction::MOVEC(target, creg, dir))
|
||||
},
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(Error::processor(Exceptions::IllegalInstruction as u32))
|
||||
Err(M68kError::Exception(Exceptions::IllegalInstruction))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_addq_subq(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_addq_subq(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
match get_size(ins) {
|
||||
Some(size) => {
|
||||
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
|
||||
|
@ -411,7 +411,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_branch(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_branch(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let mut disp = ((ins & 0xFF) as i8) as i32;
|
||||
if disp == 0 {
|
||||
disp = (self.read_instruction_word(memory)? as i16) as i32;
|
||||
|
@ -427,9 +427,9 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_moveq(&mut self, _memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_moveq(&mut self, _memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
if (ins & 0x0100) != 0 {
|
||||
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
|
||||
return Err(M68kError::Exception(Exceptions::IllegalInstruction));
|
||||
}
|
||||
let reg = get_high_reg(ins);
|
||||
let data = (ins & 0xFF) as u8;
|
||||
|
@ -437,7 +437,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_div_or(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_div_or(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let size = get_size(ins);
|
||||
|
||||
if (ins & 0x1F0) == 0x100 {
|
||||
|
@ -461,7 +461,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_sub(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_sub(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let reg = get_high_reg(ins);
|
||||
let dir = (ins & 0x0100) >> 8;
|
||||
let size = get_size(ins);
|
||||
|
@ -492,7 +492,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_cmp_eor(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_cmp_eor(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let reg = get_high_reg(ins);
|
||||
let optype = (ins & 0x0100) >> 8;
|
||||
let size = get_size(ins);
|
||||
|
@ -514,12 +514,12 @@ impl M68kDecoder {
|
|||
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
|
||||
Ok(Instruction::CMPA(target, reg, size))
|
||||
},
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_mul_and(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_mul_and(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let size = get_size(ins);
|
||||
|
||||
if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 {
|
||||
|
@ -537,7 +537,7 @@ impl M68kDecoder {
|
|||
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
|
||||
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
|
||||
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else if let Some(size) = size {
|
||||
let data_reg = Target::DirectDReg(get_high_reg(ins));
|
||||
|
@ -552,7 +552,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_group_add(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_add(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
let reg = get_high_reg(ins);
|
||||
let dir = (ins & 0x0100) >> 8;
|
||||
let size = get_size(ins);
|
||||
|
@ -582,7 +582,7 @@ impl M68kDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
fn decode_group_shift(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, Error> {
|
||||
fn decode_group_shift(&mut self, memory: &mut M68kBusPort, ins: u16) -> Result<Instruction, M68kError> {
|
||||
match get_size(ins) {
|
||||
Some(size) => {
|
||||
let target = Target::DirectDReg(get_low_reg(ins));
|
||||
|
@ -599,7 +599,7 @@ impl M68kDecoder {
|
|||
0b01 => Ok(Instruction::LSR(count, target, size)),
|
||||
0b10 => Ok(Instruction::ROXR(count, target, size)),
|
||||
0b11 => Ok(Instruction::ROR(count, target, size)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else {
|
||||
match (ins & 0x0018) >> 3 {
|
||||
|
@ -607,7 +607,7 @@ impl M68kDecoder {
|
|||
0b01 => Ok(Instruction::LSL(count, target, size)),
|
||||
0b10 => Ok(Instruction::ROXL(count, target, size)),
|
||||
0b11 => Ok(Instruction::ROL(count, target, size)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -623,7 +623,7 @@ impl M68kDecoder {
|
|||
0b01 => Ok(Instruction::LSR(count, target, size)),
|
||||
0b10 => Ok(Instruction::ROXR(count, target, size)),
|
||||
0b11 => Ok(Instruction::ROR(count, target, size)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else {
|
||||
match (ins & 0x0600) >> 9 {
|
||||
|
@ -631,7 +631,7 @@ impl M68kDecoder {
|
|||
0b01 => Ok(Instruction::LSL(count, target, size)),
|
||||
0b10 => Ok(Instruction::ROXL(count, target, size)),
|
||||
0b11 => Ok(Instruction::ROL(count, target, size)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
}
|
||||
} else if self.cputype > M68kType::MC68020 {
|
||||
|
@ -659,50 +659,50 @@ impl M68kDecoder {
|
|||
0b111 => Ok(Instruction::BFINS(reg, target, offset, width)),
|
||||
0b110 => Ok(Instruction::BFSET(target, offset, width)),
|
||||
0b000 => Ok(Instruction::BFTST(target, offset, width)),
|
||||
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
} else {
|
||||
Err(Error::processor(Exceptions::IllegalInstruction as u32))
|
||||
Err(M68kError::Exception(Exceptions::IllegalInstruction))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn read_instruction_word(&mut self, memory: &mut M68kBusPort) -> Result<u16, Error> {
|
||||
fn read_instruction_word(&mut self, memory: &mut M68kBusPort) -> Result<u16, M68kError> {
|
||||
let word = memory.read_instruction_word(self.is_supervisor, self.end)?;
|
||||
self.end += 2;
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
fn read_instruction_long(&mut self, memory: &mut M68kBusPort) -> Result<u32, Error> {
|
||||
fn read_instruction_long(&mut self, memory: &mut M68kBusPort) -> Result<u32, M68kError> {
|
||||
let word = memory.read_instruction_long(self.is_supervisor, self.end)?;
|
||||
self.end += 4;
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
fn decode_lower_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
fn decode_lower_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
let reg = get_low_reg(ins);
|
||||
let mode = get_low_mode(ins);
|
||||
self.get_mode_as_target(memory, mode, reg, size)
|
||||
}
|
||||
|
||||
fn decode_upper_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, Error> {
|
||||
fn decode_upper_effective_address(&mut self, memory: &mut M68kBusPort, ins: u16, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
let reg = get_high_reg(ins);
|
||||
let mode = get_high_mode(ins);
|
||||
self.get_mode_as_target(memory, mode, reg, size)
|
||||
}
|
||||
|
||||
fn get_extension_displacement(&mut self, memory: &mut M68kBusPort, select: u16) -> Result<i32, Error> {
|
||||
fn get_extension_displacement(&mut self, memory: &mut M68kBusPort, select: u16) -> Result<i32, M68kError> {
|
||||
let result = match select {
|
||||
0b00 | 0b01 => 0,
|
||||
0b10 => sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word),
|
||||
0b11 => self.read_instruction_long(memory)? as i32,
|
||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn decode_extension_word(&mut self, memory: &mut M68kBusPort, areg: Option<u8>) -> Result<Target, Error> {
|
||||
fn decode_extension_word(&mut self, memory: &mut M68kBusPort, areg: Option<u8>) -> Result<Target, M68kError> {
|
||||
let brief_extension = self.read_instruction_word(memory)?;
|
||||
|
||||
let use_brief = (brief_extension & 0x0100) == 0;
|
||||
|
@ -755,7 +755,7 @@ impl M68kDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_mode_as_target(&mut self, memory: &mut M68kBusPort, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
|
||||
pub(super) fn get_mode_as_target(&mut self, memory: &mut M68kBusPort, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, M68kError> {
|
||||
let value = match mode {
|
||||
0b000 => Target::DirectDReg(reg),
|
||||
0b001 => Target::DirectAReg(reg),
|
||||
|
@ -790,14 +790,14 @@ impl M68kDecoder {
|
|||
let data = match size {
|
||||
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(memory)? as u32,
|
||||
Some(Size::Long) => self.read_instruction_long(memory)?,
|
||||
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
None => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
Target::Immediate(data)
|
||||
},
|
||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
}
|
||||
},
|
||||
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||
_ => return Err(M68kError::Exception(Exceptions::IllegalInstruction)),
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ impl M68kDecoder {
|
|||
Err(err) => {
|
||||
println!("{:?}", err);
|
||||
match err {
|
||||
Error::Processor(native) if native == Exceptions::IllegalInstruction as u32 => {
|
||||
M68kError::Exception(ex) if ex == Exceptions::IllegalInstruction => {
|
||||
println!(" at {:08x}: {:04x}", self.start, memory.port.read_beu16(memory.current_clock, self.start as Address).unwrap());
|
||||
},
|
||||
_ => { },
|
||||
|
@ -825,7 +825,7 @@ impl M68kDecoder {
|
|||
}
|
||||
|
||||
pub fn dump_decoded(&mut self, memory: &mut M68kBusPort) {
|
||||
let ins_data: Result<String, Error> =
|
||||
let ins_data: Result<String, M68kError> =
|
||||
(0..((self.end - self.start) / 2)).map(|offset|
|
||||
Ok(format!("{:04x} ", memory.port.read_beu16(memory.current_clock, (self.start + (offset * 2)) as Address).unwrap()))
|
||||
).collect();
|
||||
|
|
|
@ -3,7 +3,7 @@ use femtos::{Instant, Duration};
|
|||
|
||||
use moa_core::{System, Error, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable};
|
||||
|
||||
use crate::state::{M68k, M68kType, ClockCycles, Status, Flags, Exceptions, InterruptPriority};
|
||||
use crate::state::{M68k, M68kType, M68kError, ClockCycles, Status, Flags, Exceptions, InterruptPriority};
|
||||
use crate::memory::{MemType, MemAccess};
|
||||
use crate::decode::M68kDecoder;
|
||||
use crate::timing::M68kInstructionTiming;
|
||||
|
@ -59,18 +59,44 @@ impl Transmutable for M68k {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<M68kError> for Error {
|
||||
fn from(err: M68kError) -> Self {
|
||||
match err {
|
||||
M68kError::Halted => Self::Other("cpu halted".to_string()),
|
||||
M68kError::Exception(ex) => Self::Processor(ex as u32),
|
||||
M68kError::Interrupt(num) => Self::Processor(num as u32),
|
||||
M68kError::Breakpoint => Self::Breakpoint("breakpoint".to_string()),
|
||||
M68kError::InvalidTarget(target) => Self::new(target.to_string()),
|
||||
M68kError::Other(msg) => Self::Other(msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for M68kError {
|
||||
fn from(err: Error) -> Self {
|
||||
match err {
|
||||
Error::Processor(ex) => M68kError::Interrupt(ex as u8),
|
||||
Error::Breakpoint(msg) => M68kError::Breakpoint,
|
||||
Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => M68kError::Other(format!("{}", msg)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl M68k {
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<ClockCycles, Error> {
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
||||
self.init_cycle(system.clock);
|
||||
match self.state.status {
|
||||
Status::Init => self.reset_cpu(),
|
||||
Status::Stopped => Err(Error::new("CPU stopped")),
|
||||
Status::Stopped => Err(M68kError::Halted),
|
||||
Status::Running => {
|
||||
match self.cycle_one(system) {
|
||||
Ok(diff) => Ok(diff),
|
||||
Err(Error::Processor(native)) => {
|
||||
self.exception(native as u8, false)?;
|
||||
Err(M68kError::Exception(ex)) => {
|
||||
self.exception(ex as u8, false)?;
|
||||
Ok(4)
|
||||
},
|
||||
Err(M68kError::Interrupt(ex)) => {
|
||||
self.exception(ex as u8, false)?;
|
||||
Ok(4)
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
|
@ -87,14 +113,14 @@ impl M68k {
|
|||
self.timing.reset();
|
||||
}
|
||||
|
||||
pub fn reset_cpu(&mut self) -> Result<ClockCycles, Error> {
|
||||
pub fn reset_cpu(&mut self) -> Result<ClockCycles, M68kError> {
|
||||
self.state.ssp = self.get_address_sized(0, Size::Long)?;
|
||||
self.state.pc = self.get_address_sized(4, Size::Long)?;
|
||||
self.state.status = Status::Running;
|
||||
Ok(16)
|
||||
}
|
||||
|
||||
pub fn cycle_one(&mut self, system: &System) -> Result<ClockCycles, Error> {
|
||||
pub fn cycle_one(&mut self, system: &System) -> Result<ClockCycles, M68kError> {
|
||||
self.check_breakpoints()?;
|
||||
|
||||
self.decode_next()?;
|
||||
|
@ -104,7 +130,7 @@ impl M68k {
|
|||
Ok(self.timing.calculate_clocks(false, 1))
|
||||
}
|
||||
|
||||
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), Error> {
|
||||
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), M68kError> {
|
||||
self.state.pending_ipl = match system.get_interrupt_controller().check() {
|
||||
(true, priority) => InterruptPriority::from_u8(priority),
|
||||
(false, _) => InterruptPriority::NoInterrupt,
|
||||
|
@ -132,7 +158,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), Error> {
|
||||
pub fn exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> {
|
||||
log::debug!("{}: raising exception {}", DEV_NAME, number);
|
||||
|
||||
if number == Exceptions::BusError as u8 || number == Exceptions::AddressError as u8 {
|
||||
|
@ -148,7 +174,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn setup_group0_exception(&mut self, number: u8) -> Result<(), Error> {
|
||||
pub fn setup_group0_exception(&mut self, number: u8) -> Result<(), M68kError> {
|
||||
let sr = self.state.sr;
|
||||
let ins_word = self.decoder.instruction_word;
|
||||
let extra_code = self.port.request.get_type_code();
|
||||
|
@ -177,7 +203,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), Error> {
|
||||
pub fn setup_normal_exception(&mut self, number: u8, is_interrupt: bool) -> Result<(), M68kError> {
|
||||
let sr = self.state.sr;
|
||||
self.port.request.i_n_bit = true;
|
||||
|
||||
|
@ -202,7 +228,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_next(&mut self) -> Result<(), Error> {
|
||||
pub fn decode_next(&mut self) -> Result<(), M68kError> {
|
||||
let is_supervisor = self.is_supervisor();
|
||||
self.decoder.decode_at(&mut self.port, is_supervisor, self.state.pc)?;
|
||||
|
||||
|
@ -213,7 +239,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute_current(&mut self) -> Result<(), Error> {
|
||||
pub fn execute_current(&mut self) -> Result<(), M68kError> {
|
||||
match self.decoder.instruction {
|
||||
Instruction::ABCD(src, dest) => self.execute_abcd(src, dest),
|
||||
Instruction::ADD(src, dest, size) => self.execute_add(src, dest, size),
|
||||
|
@ -303,13 +329,13 @@ impl M68k {
|
|||
Instruction::UNLK(reg) => self.execute_unlk(reg),
|
||||
Instruction::UnimplementedA(value) => self.execute_unimplemented_a(value),
|
||||
Instruction::UnimplementedF(value) => self.execute_unimplemented_f(value),
|
||||
_ => { return Err(Error::new("Unsupported instruction")); },
|
||||
_ => { return Err(M68kError::Other("Unsupported instruction".to_string())); },
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_abcd(&mut self, src: Target, dest: Target) -> Result<(), Error> {
|
||||
fn execute_abcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, Size::Byte, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
||||
|
||||
|
@ -333,7 +359,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_add(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_add(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let (result, carry) = overflowing_add_sized(dest_val, src_val, size);
|
||||
|
@ -344,7 +370,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_adda(&mut self, src: Target, dest: Register, size: Size) -> Result<(), Error> {
|
||||
fn execute_adda(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError> {
|
||||
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 (result, _) = overflowing_add_sized(dest_val, src_val, Size::Long);
|
||||
|
@ -352,7 +378,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_addx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_addx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let extend = self.get_flag(Flags::Extend) as u32;
|
||||
|
@ -373,7 +399,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_and(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_and(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let result = get_value_sized(dest_val & src_val, size);
|
||||
|
@ -382,18 +408,18 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_and_to_ccr(&mut self, value: u8) -> Result<(), Error> {
|
||||
fn execute_and_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
||||
self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) & (value as u16));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_and_to_sr(&mut self, value: u16) -> Result<(), Error> {
|
||||
fn execute_and_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
self.set_sr(self.state.sr & value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_asl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_asl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let value = self.get_target_value(target, size, Used::Twice)?;
|
||||
|
||||
|
@ -413,7 +439,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_asr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_asr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let value = self.get_target_value(target, size, Used::Twice)?;
|
||||
|
||||
|
@ -446,7 +472,7 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), Error> {
|
||||
fn execute_bcc(&mut self, cond: Condition, offset: i32) -> Result<(), M68kError> {
|
||||
let should_branch = self.get_current_condition(cond);
|
||||
if should_branch {
|
||||
if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
||||
|
@ -457,7 +483,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bra(&mut self, offset: i32) -> Result<(), Error> {
|
||||
fn execute_bra(&mut self, offset: i32) -> Result<(), M68kError> {
|
||||
if let Err(err) = self.set_pc(self.decoder.start.wrapping_add(2).wrapping_add(offset as u32)) {
|
||||
self.state.pc -= 2;
|
||||
return Err(err);
|
||||
|
@ -465,7 +491,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bsr(&mut self, offset: i32) -> Result<(), Error> {
|
||||
fn execute_bsr(&mut self, offset: i32) -> Result<(), M68kError> {
|
||||
self.push_long(self.state.pc)?;
|
||||
let sp = *self.get_stack_pointer_mut();
|
||||
self.debugger.stack_tracer.push_return(sp);
|
||||
|
@ -476,7 +502,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bchg(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_bchg(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
||||
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
||||
|
@ -485,7 +511,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bclr(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_bclr(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
|
||||
let mask = self.set_bit_test_flags(src_val, bitnum, size);
|
||||
|
@ -494,7 +520,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bset(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_bset(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
||||
let mask = self.set_bit_test_flags(value, bitnum, size);
|
||||
|
@ -503,14 +529,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_btst(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_btst(&mut self, bitnum: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
|
||||
let value = self.get_target_value(target, size, Used::Once)?;
|
||||
self.set_bit_test_flags(value, bitnum, size);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bfchg(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> {
|
||||
fn execute_bfchg(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||
|
@ -520,7 +546,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bfclr(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> {
|
||||
fn execute_bfclr(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||
|
@ -530,7 +556,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bfexts(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), Error> {
|
||||
fn execute_bfexts(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||
|
@ -546,7 +572,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bfextu(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), Error> {
|
||||
fn execute_bfextu(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate, reg: Register) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||
|
@ -556,7 +582,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bfset(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> {
|
||||
fn execute_bfset(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Twice)?;
|
||||
|
@ -566,7 +592,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_bftst(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), Error> {
|
||||
fn execute_bftst(&mut self, target: Target, offset: RegOrImmediate, width: RegOrImmediate) -> Result<(), M68kError> {
|
||||
let (offset, width) = self.get_bit_field_args(offset, width);
|
||||
let mask = get_bit_field_mask(offset, width);
|
||||
let value = self.get_target_value(target, Size::Long, Used::Once)?;
|
||||
|
@ -575,7 +601,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_chk(&mut self, target: Target, reg: Register, size: Size) -> Result<(), Error> {
|
||||
fn execute_chk(&mut self, target: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
||||
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);
|
||||
|
||||
|
@ -591,7 +617,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_clr(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
if self.cputype == M68kType::MC68000 {
|
||||
self.get_target_value(target, size, Used::Twice)?;
|
||||
self.set_target_value(target, 0, size, Used::Twice)?;
|
||||
|
@ -603,7 +629,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_cmp(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_cmp(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, 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);
|
||||
|
@ -612,7 +638,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_cmpa(&mut self, src: Target, reg: Register, size: Size) -> Result<(), Error> {
|
||||
fn execute_cmpa(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
||||
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 (result, carry) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
||||
|
@ -621,7 +647,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_dbcc(&mut self, cond: Condition, reg: Register, offset: i16) -> Result<(), Error> {
|
||||
fn execute_dbcc(&mut self, cond: Condition, reg: Register, offset: i16) -> Result<(), M68kError> {
|
||||
let condition_true = self.get_current_condition(cond);
|
||||
if !condition_true {
|
||||
let next = ((get_value_sized(self.state.d_reg[reg as usize], Size::Word) as u16) as i16).wrapping_sub(1);
|
||||
|
@ -636,7 +662,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_divw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), Error> {
|
||||
fn execute_divw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, Size::Word, Used::Once)?;
|
||||
if src_val == 0 {
|
||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||
|
@ -676,7 +702,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_divl(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), Error> {
|
||||
fn execute_divl(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, Size::Long, Used::Once)?;
|
||||
if src_val == 0 {
|
||||
self.exception(Exceptions::ZeroDivide as u8, false)?;
|
||||
|
@ -709,7 +735,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_eor(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_eor(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let result = get_value_sized(dest_val ^ src_val, size);
|
||||
|
@ -718,18 +744,18 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_eor_to_ccr(&mut self, value: u8) -> Result<(), Error> {
|
||||
fn execute_eor_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
||||
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_eor_to_sr(&mut self, value: u16) -> Result<(), Error> {
|
||||
fn execute_eor_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
self.set_sr(self.state.sr ^ value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_exg(&mut self, target1: Target, target2: Target) -> Result<(), Error> {
|
||||
fn execute_exg(&mut self, target1: Target, target2: Target) -> Result<(), M68kError> {
|
||||
let value1 = self.get_target_value(target1, 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)?;
|
||||
|
@ -737,7 +763,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_ext(&mut self, reg: Register, from_size: Size, to_size: Size) -> Result<(), Error> {
|
||||
fn execute_ext(&mut self, reg: Register, from_size: Size, to_size: Size) -> Result<(), M68kError> {
|
||||
let input = get_value_sized(self.state.d_reg[reg as usize], from_size);
|
||||
let result = match (from_size, to_size) {
|
||||
(Size::Byte, Size::Word) => ((((input as u8) as i8) as i16) as u16) as u32,
|
||||
|
@ -750,12 +776,12 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_illegal(&mut self) -> Result<(), Error> {
|
||||
fn execute_illegal(&mut self) -> Result<(), M68kError> {
|
||||
self.exception(Exceptions::IllegalInstruction as u8, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_jmp(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_jmp(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
let addr = self.get_target_address(target)?;
|
||||
if let Err(err) = self.set_pc(addr) {
|
||||
self.state.pc -= 2;
|
||||
|
@ -764,7 +790,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_jsr(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_jsr(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
let previous_pc = self.state.pc;
|
||||
let addr = self.get_target_address(target)?;
|
||||
if let Err(err) = self.set_pc(addr) {
|
||||
|
@ -779,14 +805,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_lea(&mut self, target: Target, reg: Register) -> Result<(), Error> {
|
||||
fn execute_lea(&mut self, target: Target, reg: Register) -> Result<(), M68kError> {
|
||||
let value = self.get_target_address(target)?;
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
*addr = value;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_link(&mut self, reg: Register, offset: i32) -> Result<(), Error> {
|
||||
fn execute_link(&mut self, reg: Register, offset: i32) -> Result<(), M68kError> {
|
||||
*self.get_stack_pointer_mut() -= 4;
|
||||
let sp = *self.get_stack_pointer_mut();
|
||||
let value = *self.get_a_reg_mut(reg);
|
||||
|
@ -796,7 +822,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_lsl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_lsl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -808,7 +834,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_lsr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_lsr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -831,14 +857,14 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_move(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
self.set_logic_flags(src_val, size);
|
||||
self.set_target_value(dest, src_val, size, Used::Once)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_movea(&mut self, src: Target, reg: Register, size: Size) -> Result<(), Error> {
|
||||
fn execute_movea(&mut self, src: Target, reg: Register, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let src_val = sign_extend_to_long(src_val, size) as u32;
|
||||
let addr = self.get_a_reg_mut(reg);
|
||||
|
@ -846,26 +872,26 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_move_from_sr(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_move_from_sr(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
self.set_target_value(target, self.state.sr as u32, Size::Word, Used::Once)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_move_to_sr(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_move_to_sr(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
||||
self.set_sr(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_move_to_ccr(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_move_to_ccr(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
let value = self.get_target_value(target, Size::Word, Used::Once)? as u16;
|
||||
self.set_sr((self.state.sr & 0xFF00) | (value & 0x00FF));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_movec(&mut self, target: Target, control_reg: ControlRegister, dir: Direction) -> Result<(), Error> {
|
||||
fn execute_movec(&mut self, target: Target, control_reg: ControlRegister, dir: Direction) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
match dir {
|
||||
Direction::FromTarget => {
|
||||
|
@ -882,7 +908,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), Error> {
|
||||
fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mask: u16) -> Result<(), M68kError> {
|
||||
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
|
||||
|
@ -899,13 +925,13 @@ impl M68k {
|
|||
let post_addr = match target {
|
||||
Target::IndirectARegInc(_) => {
|
||||
if dir != Direction::FromTarget {
|
||||
return Err(Error::new(format!("Cannot use {:?} with {:?}", target, dir)));
|
||||
return Err(M68kError::Other(format!("Cannot use {:?} with {:?}", target, dir)));
|
||||
}
|
||||
self.move_memory_to_registers(addr, size, mask)?
|
||||
},
|
||||
Target::IndirectARegDec(_) => {
|
||||
if dir != Direction::ToTarget {
|
||||
return Err(Error::new(format!("Cannot use {:?} with {:?}", target, dir)));
|
||||
return Err(M68kError::Other(format!("Cannot use {:?} with {:?}", target, dir)));
|
||||
}
|
||||
self.move_registers_to_memory_reverse(addr, size, mask)?
|
||||
},
|
||||
|
@ -929,7 +955,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn move_memory_to_registers(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, Error> {
|
||||
fn move_memory_to_registers(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
||||
for i in 0..8 {
|
||||
if (mask & 0x01) != 0 {
|
||||
self.state.d_reg[i] = sign_extend_to_long(self.get_address_sized(addr as Address, size)?, size) as u32;
|
||||
|
@ -947,7 +973,7 @@ impl M68k {
|
|||
Ok(addr)
|
||||
}
|
||||
|
||||
fn move_registers_to_memory(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, Error> {
|
||||
fn move_registers_to_memory(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
||||
for i in 0..8 {
|
||||
if (mask & 0x01) != 0 {
|
||||
self.set_address_sized(addr as Address, self.state.d_reg[i], size)?;
|
||||
|
@ -966,7 +992,7 @@ impl M68k {
|
|||
Ok(addr)
|
||||
}
|
||||
|
||||
fn move_registers_to_memory_reverse(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, Error> {
|
||||
fn move_registers_to_memory_reverse(&mut self, mut addr: u32, size: Size, mut mask: u16) -> Result<u32, M68kError> {
|
||||
for i in (0..8).rev() {
|
||||
if (mask & 0x01) != 0 {
|
||||
let value = *self.get_a_reg_mut(i);
|
||||
|
@ -985,7 +1011,7 @@ impl M68k {
|
|||
Ok(addr)
|
||||
}
|
||||
|
||||
fn execute_movep(&mut self, dreg: Register, areg: Register, offset: i16, size: Size, dir: Direction) -> Result<(), Error> {
|
||||
fn execute_movep(&mut self, dreg: Register, areg: Register, offset: i16, size: Size, dir: Direction) -> Result<(), M68kError> {
|
||||
match dir {
|
||||
Direction::ToTarget => {
|
||||
let mut shift = (size.in_bits() as i32) - 8;
|
||||
|
@ -1011,14 +1037,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_moveq(&mut self, data: u8, reg: Register) -> Result<(), Error> {
|
||||
fn execute_moveq(&mut self, data: u8, reg: Register) -> Result<(), M68kError> {
|
||||
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
|
||||
self.state.d_reg[reg as usize] = value;
|
||||
self.set_logic_flags(value, Size::Long);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_moveusp(&mut self, target: Target, dir: Direction) -> Result<(), Error> {
|
||||
fn execute_moveusp(&mut self, target: Target, dir: Direction) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
match dir {
|
||||
Direction::ToTarget => self.set_target_value(target, self.state.usp, Size::Long, Used::Once)?,
|
||||
|
@ -1027,7 +1053,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_mulw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), Error> {
|
||||
fn execute_mulw(&mut self, src: Target, dest: Register, sign: Sign) -> Result<(), M68kError> {
|
||||
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 result = match sign {
|
||||
|
@ -1040,7 +1066,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_mull(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), Error> {
|
||||
fn execute_mull(&mut self, src: Target, dest_h: Option<Register>, dest_l: Register, sign: Sign) -> Result<(), M68kError> {
|
||||
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 result = match sign {
|
||||
|
@ -1056,14 +1082,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_nbcd(&mut self, dest: Target) -> Result<(), Error> {
|
||||
fn execute_nbcd(&mut self, dest: Target) -> Result<(), M68kError> {
|
||||
let dest_val = self.get_target_value(dest, Size::Byte, Used::Twice)?;
|
||||
let result = self.execute_sbcd_val(dest_val, 0)?;
|
||||
self.set_target_value(dest, result, Size::Byte, Used::Twice)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_neg(&mut self, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_neg(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let original = self.get_target_value(target, size, Used::Twice)?;
|
||||
let (result, overflow) = overflowing_sub_signed_sized(0, original, size);
|
||||
let carry = result != 0;
|
||||
|
@ -1073,7 +1099,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_negx(&mut self, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_negx(&mut self, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let extend = self.get_flag(Flags::Extend) as u32;
|
||||
let (result1, carry1) = overflowing_sub_sized(0, dest_val, size);
|
||||
|
@ -1093,7 +1119,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_not(&mut self, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_not(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let mut value = self.get_target_value(target, size, Used::Twice)?;
|
||||
value = get_value_sized(!value, size);
|
||||
self.set_target_value(target, value, size, Used::Twice)?;
|
||||
|
@ -1101,7 +1127,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_or(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_or(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let result = get_value_sized(dest_val | src_val, size);
|
||||
|
@ -1110,30 +1136,30 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_or_to_ccr(&mut self, value: u8) -> Result<(), Error> {
|
||||
fn execute_or_to_ccr(&mut self, value: u8) -> Result<(), M68kError> {
|
||||
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) | (value as u16)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_or_to_sr(&mut self, value: u16) -> Result<(), Error> {
|
||||
fn execute_or_to_sr(&mut self, value: u16) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
self.set_sr(self.state.sr | value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_pea(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_pea(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
let value = self.get_target_address(target)?;
|
||||
self.push_long(value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_reset(&mut self) -> Result<(), Error> {
|
||||
fn execute_reset(&mut self) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
// TODO this only resets external devices and not internal ones
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_rol(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_rol(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -1144,7 +1170,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_ror(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_ror(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -1155,7 +1181,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_roxl(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_roxl(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -1167,7 +1193,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_roxr(&mut self, count: Target, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_roxr(&mut self, count: Target, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let count = self.get_target_value(count, size, Used::Once)? % 64;
|
||||
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
|
||||
for _ in 0..count {
|
||||
|
@ -1186,7 +1212,7 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
fn execute_rte(&mut self) -> Result<(), Error> {
|
||||
fn execute_rte(&mut self) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
let sr = self.pop_word()?;
|
||||
let addr = self.pop_long()?;
|
||||
|
@ -1203,7 +1229,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_rtr(&mut self) -> Result<(), Error> {
|
||||
fn execute_rtr(&mut self) -> Result<(), M68kError> {
|
||||
let ccr = self.pop_word()?;
|
||||
let addr = self.pop_long()?;
|
||||
self.set_sr((self.state.sr & 0xFF00) | (ccr & 0x00FF));
|
||||
|
@ -1214,7 +1240,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_rts(&mut self) -> Result<(), Error> {
|
||||
fn execute_rts(&mut self) -> Result<(), M68kError> {
|
||||
self.debugger.stack_tracer.pop_return();
|
||||
let addr = self.pop_long()?;
|
||||
if let Err(err) = self.set_pc(addr) {
|
||||
|
@ -1224,7 +1250,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_scc(&mut self, cond: Condition, target: Target) -> Result<(), Error> {
|
||||
fn execute_scc(&mut self, cond: Condition, target: Target) -> Result<(), M68kError> {
|
||||
let condition_true = self.get_current_condition(cond);
|
||||
if condition_true {
|
||||
self.set_target_value(target, 0xFF, Size::Byte, Used::Once)?;
|
||||
|
@ -1234,14 +1260,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_stop(&mut self, flags: u16) -> Result<(), Error> {
|
||||
fn execute_stop(&mut self, flags: u16) -> Result<(), M68kError> {
|
||||
self.require_supervisor()?;
|
||||
self.set_sr(flags);
|
||||
self.state.status = Status::Stopped;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_sbcd(&mut self, src: Target, dest: Target) -> Result<(), Error> {
|
||||
fn execute_sbcd(&mut self, src: Target, dest: Target) -> Result<(), M68kError> {
|
||||
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 result = self.execute_sbcd_val(src_val, dest_val)?;
|
||||
|
@ -1249,7 +1275,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_sbcd_val(&mut self, src_val: u32, dest_val: u32) -> Result<u32, Error> {
|
||||
fn execute_sbcd_val(&mut self, src_val: u32, dest_val: u32) -> Result<u32, M68kError> {
|
||||
let extend_flag = self.get_flag(Flags::Extend) as u32;
|
||||
let src_parts = get_nibbles_from_byte(src_val);
|
||||
let dest_parts = get_nibbles_from_byte(dest_val);
|
||||
|
@ -1270,7 +1296,7 @@ impl M68k {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn execute_sub(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_sub(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let (result, carry) = overflowing_sub_sized(dest_val, src_val, size);
|
||||
|
@ -1281,7 +1307,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_suba(&mut self, src: Target, dest: Register, size: Size) -> Result<(), Error> {
|
||||
fn execute_suba(&mut self, src: Target, dest: Register, size: Size) -> Result<(), M68kError> {
|
||||
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 (result, _) = overflowing_sub_sized(dest_val, src_val, Size::Long);
|
||||
|
@ -1289,7 +1315,7 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_subx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_subx(&mut self, src: Target, dest: Target, size: Size) -> Result<(), M68kError> {
|
||||
let src_val = self.get_target_value(src, size, Used::Once)?;
|
||||
let dest_val = self.get_target_value(dest, size, Used::Twice)?;
|
||||
let extend = self.get_flag(Flags::Extend) as u32;
|
||||
|
@ -1310,14 +1336,14 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_swap(&mut self, reg: Register) -> Result<(), Error> {
|
||||
fn execute_swap(&mut self, reg: Register) -> Result<(), M68kError> {
|
||||
let value = self.state.d_reg[reg as usize];
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_tas(&mut self, target: Target) -> Result<(), Error> {
|
||||
fn execute_tas(&mut self, target: Target) -> Result<(), M68kError> {
|
||||
let value = self.get_target_value(target, Size::Byte, Used::Twice)?;
|
||||
self.set_flag(Flags::Negative, (value & 0x80) != 0);
|
||||
self.set_flag(Flags::Zero, value == 0);
|
||||
|
@ -1327,25 +1353,25 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_tst(&mut self, target: Target, size: Size) -> Result<(), Error> {
|
||||
fn execute_tst(&mut self, target: Target, size: Size) -> Result<(), M68kError> {
|
||||
let value = self.get_target_value(target, size, Used::Once)?;
|
||||
self.set_logic_flags(value, size);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_trap(&mut self, number: u8) -> Result<(), Error> {
|
||||
fn execute_trap(&mut self, number: u8) -> Result<(), M68kError> {
|
||||
self.exception(32 + number, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_trapv(&mut self) -> Result<(), Error> {
|
||||
fn execute_trapv(&mut self) -> Result<(), M68kError> {
|
||||
if self.get_flag(Flags::Overflow) {
|
||||
self.exception(Exceptions::TrapvInstruction as u8, false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_unlk(&mut self, reg: Register) -> Result<(), Error> {
|
||||
fn execute_unlk(&mut self, reg: Register) -> Result<(), M68kError> {
|
||||
let value = *self.get_a_reg_mut(reg);
|
||||
*self.get_stack_pointer_mut() = value;
|
||||
let new_value = self.pop_long()?;
|
||||
|
@ -1354,20 +1380,20 @@ impl M68k {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_unimplemented_a(&mut self, _: u16) -> Result<(), Error> {
|
||||
fn execute_unimplemented_a(&mut self, _: u16) -> Result<(), M68kError> {
|
||||
self.state.pc -= 2;
|
||||
self.exception(Exceptions::LineAEmulator as u8, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_unimplemented_f(&mut self, _: u16) -> Result<(), Error> {
|
||||
fn execute_unimplemented_f(&mut self, _: u16) -> Result<(), M68kError> {
|
||||
self.state.pc -= 2;
|
||||
self.exception(Exceptions::LineFEmulator as u8, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub(super) fn get_target_value(&mut self, target: Target, size: Size, used: Used) -> Result<u32, Error> {
|
||||
pub(super) fn get_target_value(&mut self, target: Target, size: Size, used: Used) -> Result<u32, M68kError> {
|
||||
match target {
|
||||
Target::Immediate(value) => Ok(value),
|
||||
Target::DirectDReg(reg) => Ok(get_value_sized(self.state.d_reg[reg as usize], size)),
|
||||
|
@ -1407,7 +1433,7 @@ impl M68k {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_target_value(&mut self, target: Target, value: u32, size: Size, used: Used) -> Result<(), Error> {
|
||||
pub(super) fn set_target_value(&mut self, target: Target, value: u32, size: Size, used: Used) -> Result<(), M68kError> {
|
||||
match target {
|
||||
Target::DirectDReg(reg) => {
|
||||
set_value_sized(&mut self.state.d_reg[reg as usize], value, size);
|
||||
|
@ -1447,12 +1473,12 @@ impl M68k {
|
|||
Target::IndirectMemory(addr, _) => {
|
||||
self.set_address_sized(addr as Address, value, size)?;
|
||||
},
|
||||
_ => return Err(Error::new(format!("Unimplemented addressing target: {:?}", target))),
|
||||
Target::Immediate(_) => return Err(M68kError::InvalidTarget(target)),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_target_address(&mut self, target: Target) -> Result<u32, Error> {
|
||||
fn get_target_address(&mut self, target: Target) -> Result<u32, M68kError> {
|
||||
let addr = match target {
|
||||
Target::IndirectAReg(reg) | Target::IndirectARegInc(reg) | Target::IndirectARegDec(reg) => *self.get_a_reg_mut(reg),
|
||||
Target::IndirectRegOffset(base_reg, index_reg, displacement) => {
|
||||
|
@ -1475,7 +1501,7 @@ impl M68k {
|
|||
Target::IndirectMemory(addr, _) => {
|
||||
addr
|
||||
},
|
||||
_ => return Err(Error::new(format!("Invalid addressing target: {:?}", target))),
|
||||
_ => return Err(M68kError::InvalidTarget(target)),
|
||||
};
|
||||
Ok(addr)
|
||||
}
|
||||
|
@ -1507,22 +1533,23 @@ impl M68k {
|
|||
*reg_addr
|
||||
}
|
||||
|
||||
fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, Error> {
|
||||
fn get_address_sized(&mut self, addr: Address, size: Size) -> Result<u32, M68kError> {
|
||||
self.port.read_data_sized(self.is_supervisor(), addr, size)
|
||||
}
|
||||
|
||||
fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), Error> {
|
||||
fn set_address_sized(&mut self, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
|
||||
self.port.write_data_sized(self.is_supervisor(), addr, value, size)
|
||||
}
|
||||
|
||||
fn push_word(&mut self, value: u16) -> Result<(), Error> {
|
||||
fn push_word(&mut self, value: u16) -> Result<(), M68kError> {
|
||||
*self.get_stack_pointer_mut() -= 2;
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Write, MemType::Data, false)?;
|
||||
self.port.port.write_beu16(self.current_clock, addr as Address, value)
|
||||
self.port.port.write_beu16(self.current_clock, addr as Address, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pop_word(&mut self) -> Result<u16, Error> {
|
||||
fn pop_word(&mut self) -> Result<u16, M68kError> {
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.start_request(self.is_supervisor(), addr, Size::Word, MemAccess::Read, MemType::Data, false)?;
|
||||
let value = self.port.port.read_beu16(self.current_clock, addr as Address)?;
|
||||
|
@ -1530,14 +1557,15 @@ impl M68k {
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
fn push_long(&mut self, value: u32) -> Result<(), Error> {
|
||||
fn push_long(&mut self, value: u32) -> Result<(), M68kError> {
|
||||
*self.get_stack_pointer_mut() -= 4;
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Write, MemType::Data, false)?;
|
||||
self.port.port.write_beu32(self.current_clock, addr as Address, value)
|
||||
self.port.port.write_beu32(self.current_clock, addr as Address, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pop_long(&mut self) -> Result<u32, Error> {
|
||||
fn pop_long(&mut self) -> Result<u32, M68kError> {
|
||||
let addr = *self.get_stack_pointer_mut();
|
||||
self.port.start_request(self.is_supervisor(), addr, Size::Long, MemAccess::Read, MemType::Data, false)?;
|
||||
let value = self.port.port.read_beu32(self.current_clock, addr as Address)?;
|
||||
|
@ -1545,7 +1573,7 @@ impl M68k {
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
fn set_pc(&mut self, value: u32) -> Result<(), Error> {
|
||||
fn set_pc(&mut self, value: u32) -> Result<(), M68kError> {
|
||||
self.state.pc = value;
|
||||
self.port.start_request(self.is_supervisor(), self.state.pc, Size::Word, MemAccess::Read, MemType::Program, true)?;
|
||||
Ok(())
|
||||
|
@ -1622,11 +1650,11 @@ impl M68k {
|
|||
self.state.sr & (Flags:: Supervisor as u16) != 0
|
||||
}
|
||||
|
||||
fn require_supervisor(&self) -> Result<(), Error> {
|
||||
fn require_supervisor(&self) -> Result<(), M68kError> {
|
||||
if self.is_supervisor() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::processor(Exceptions::PrivilegeViolation as u32))
|
||||
Err(M68kError::Exception(Exceptions::PrivilegeViolation))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use femtos::Instant;
|
|||
|
||||
use moa_core::{Error, Address, Addressable, BusPort};
|
||||
|
||||
use crate::state::{M68k, Exceptions};
|
||||
use crate::state::{M68k, M68kError, Exceptions};
|
||||
use crate::instructions::Size;
|
||||
|
||||
#[repr(u8)]
|
||||
|
@ -120,35 +120,35 @@ impl M68kBusPort {
|
|||
self.current_clock = clock;
|
||||
}
|
||||
|
||||
pub(crate) fn read_instruction_word(&mut self, is_supervisor: bool, addr: u32) -> Result<u16, Error> {
|
||||
pub(crate) fn read_instruction_word(&mut self, is_supervisor: bool, addr: u32) -> Result<u16, M68kError> {
|
||||
self.start_instruction_request(is_supervisor, addr)?;
|
||||
self.port.read_beu16(self.current_clock, addr as Address)
|
||||
Ok(self.port.read_beu16(self.current_clock, addr as Address)?)
|
||||
}
|
||||
|
||||
pub(crate) fn read_instruction_long(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, Error> {
|
||||
pub(crate) fn read_instruction_long(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
|
||||
self.start_instruction_request(is_supervisor, addr)?;
|
||||
self.port.read_beu32(self.current_clock, addr as Address)
|
||||
Ok(self.port.read_beu32(self.current_clock, addr as Address)?)
|
||||
}
|
||||
|
||||
pub(crate) fn read_data_sized(&mut self, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, Error> {
|
||||
pub(crate) fn read_data_sized(&mut self, is_supervisor: bool, addr: Address, size: Size) -> Result<u32, M68kError> {
|
||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Read, MemType::Data, false)?;
|
||||
match size {
|
||||
Ok(match size {
|
||||
Size::Byte => self.port.read_u8(self.current_clock, addr).map(|value| value as u32),
|
||||
Size::Word => self.port.read_beu16(self.current_clock, addr).map(|value| value as u32),
|
||||
Size::Long => self.port.read_beu32(self.current_clock, addr),
|
||||
}
|
||||
}?)
|
||||
}
|
||||
|
||||
pub(crate) fn write_data_sized(&mut self, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), Error> {
|
||||
pub(crate) fn write_data_sized(&mut self, is_supervisor: bool, addr: Address, value: u32, size: Size) -> Result<(), M68kError> {
|
||||
self.start_request(is_supervisor, addr as u32, size, MemAccess::Write, MemType::Data, false)?;
|
||||
match size {
|
||||
Ok(match size {
|
||||
Size::Byte => self.port.write_u8(self.current_clock, addr, value as u8),
|
||||
Size::Word => self.port.write_beu16(self.current_clock, addr, value as u16),
|
||||
Size::Long => self.port.write_beu32(self.current_clock, addr, value),
|
||||
}
|
||||
}?)
|
||||
}
|
||||
|
||||
pub(crate) fn start_instruction_request(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, Error> {
|
||||
pub(crate) fn start_instruction_request(&mut self, is_supervisor: bool, addr: u32) -> Result<u32, M68kError> {
|
||||
self.request.i_n_bit = false;
|
||||
self.request.code = FunctionCode::program(is_supervisor);
|
||||
self.request.access = MemAccess::Read;
|
||||
|
@ -157,7 +157,7 @@ impl M68kBusPort {
|
|||
validate_address(addr)
|
||||
}
|
||||
|
||||
pub(crate) fn start_request(&mut self, is_supervisor: bool, addr: u32, size: Size, access: MemAccess, mtype: MemType, i_n_bit: bool) -> Result<u32, Error> {
|
||||
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> {
|
||||
self.request.i_n_bit = i_n_bit;
|
||||
self.request.code = match mtype {
|
||||
MemType::Program => FunctionCode::program(is_supervisor),
|
||||
|
@ -179,11 +179,11 @@ impl M68kBusPort {
|
|||
}
|
||||
}
|
||||
|
||||
fn validate_address(addr: u32) -> Result<u32, Error> {
|
||||
fn validate_address(addr: u32) -> Result<u32, M68kError> {
|
||||
if addr & 0x1 == 0 {
|
||||
Ok(addr)
|
||||
} else {
|
||||
Err(Error::processor(Exceptions::AddressError as u32))
|
||||
Err(M68kError::Exception(Exceptions::AddressError))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,15 +210,15 @@ impl TargetAccess {
|
|||
|
||||
}
|
||||
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, Error> {
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), Error> {
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn complete(&self) -> Result<Self, Error> {
|
||||
pub(crate) fn complete(&self) -> Result<Self, M68kError> {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -257,11 +257,11 @@ pub(crate) struct ReadOnceAccess {
|
|||
}
|
||||
|
||||
impl ReadOnceAccess {
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, Error> {
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn complete(&self) -> Result<Self, Error> {
|
||||
pub(crate) fn complete(&self) -> Result<Self, M68kError> {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -272,15 +272,15 @@ pub(crate) struct ReadUpdateAccess {
|
|||
}
|
||||
|
||||
impl ReadUpdateAccess {
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, Error> {
|
||||
pub(crate) fn get(&mut self, cpu: &M68k) -> Result<u32, M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), Error> {
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn complete(&self) -> Result<Self, Error> {
|
||||
pub(crate) fn complete(&self) -> Result<Self, M68kError> {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -291,11 +291,11 @@ pub(crate) struct WriteOnceAccess {
|
|||
}
|
||||
|
||||
impl WriteOnceAccess {
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), Error> {
|
||||
pub(crate) fn set(&mut self, cpu: &M68k, value: u32) -> Result<(), M68kError> {
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn complete(&self) -> Result<Self, Error> {
|
||||
pub(crate) fn complete(&self) -> Result<Self, M68kError> {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::decode::M68kDecoder;
|
|||
use crate::debugger::M68kDebugger;
|
||||
use crate::memory::M68kBusPort;
|
||||
use crate::timing::M68kInstructionTiming;
|
||||
use crate::instructions::Target;
|
||||
|
||||
|
||||
pub type ClockCycles = u16;
|
||||
|
@ -91,6 +92,22 @@ pub struct M68kState {
|
|||
pub vbr: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
pub enum M68kError {
|
||||
#[error("cpu halted")]
|
||||
Halted,
|
||||
#[error("processor exception {0:?}")]
|
||||
Exception(Exceptions),
|
||||
#[error("interrupt vector {0} occurred")]
|
||||
Interrupt(u8),
|
||||
#[error("breakpoint reached")]
|
||||
Breakpoint,
|
||||
#[error("invalid instruction target, direct value used as a pointer: {0:?}")]
|
||||
InvalidTarget(Target),
|
||||
#[error("error: {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct M68k {
|
||||
pub cputype: M68kType,
|
||||
|
|
|
@ -251,7 +251,8 @@ mod decode_unit_tests {
|
|||
|
||||
#[cfg(test)]
|
||||
mod execute_unit_tests {
|
||||
use moa_core::{System, MemoryBlock, BusPort, Instant, Frequency, Address, Addressable, Steppable, Device};
|
||||
use femtos::{Instant, Frequency};
|
||||
use moa_core::{System, MemoryBlock, BusPort, Address, Addressable, Steppable, Device};
|
||||
|
||||
use crate::{M68k, M68kType};
|
||||
use crate::execute::Used;
|
||||
|
|
Loading…
Reference in New Issue