mirror of
https://github.com/transistorfet/moa.git
synced 2025-08-15 10:27:30 +00:00
Refactored and fixed some warnings
This commit is contained in:
@@ -124,7 +124,7 @@ impl M68k {
|
|||||||
},
|
},
|
||||||
"dis" | "disassemble" => {
|
"dis" | "disassemble" => {
|
||||||
let mut decoder = M68kDecoder::new(self.cputype, 0, 0);
|
let mut decoder = M68kDecoder::new(self.cputype, 0, 0);
|
||||||
decoder.dump_disassembly(system, self.state.pc, 0x1000);
|
//decoder.dump_disassembly(system, self.state.pc, 0x1000);
|
||||||
},
|
},
|
||||||
"so" | "stepout" => {
|
"so" | "stepout" => {
|
||||||
self.debugger.step_until_return = Some(self.debugger.stack_tracer.calls.len() - 1);
|
self.debugger.step_until_return = Some(self.debugger.stack_tracer.calls.len() - 1);
|
||||||
|
@@ -3,10 +3,10 @@ use std::fmt;
|
|||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::system::System;
|
use crate::system::System;
|
||||||
use crate::memory::Address;
|
use crate::memory::{Address, Addressable};
|
||||||
use crate::devices::AddressableDeviceRefMut;
|
use crate::devices::AddressableDeviceRefMut;
|
||||||
|
|
||||||
use super::state::{M68kType, ERR_ILLEGAL_INSTRUCTION};
|
use super::state::{M68kType, Exceptions};
|
||||||
|
|
||||||
|
|
||||||
const OPCG_BIT_OPS: u8 = 0x0;
|
const OPCG_BIT_OPS: u8 = 0x0;
|
||||||
@@ -19,11 +19,14 @@ const OPCG_BRANCH: u8 = 0x6;
|
|||||||
const OPCG_MOVEQ: u8 = 0x7;
|
const OPCG_MOVEQ: u8 = 0x7;
|
||||||
const OPCG_DIV_OR: u8 = 0x8;
|
const OPCG_DIV_OR: u8 = 0x8;
|
||||||
const OPCG_SUB: u8 = 0x9;
|
const OPCG_SUB: u8 = 0x9;
|
||||||
const OPCG_RESERVED1: u8 = 0xA;
|
|
||||||
const OPCG_CMP_EOR: u8 = 0xB;
|
const OPCG_CMP_EOR: u8 = 0xB;
|
||||||
const OPCG_MUL_AND: u8 = 0xC;
|
const OPCG_MUL_AND: u8 = 0xC;
|
||||||
const OPCG_ADD: u8 = 0xD;
|
const OPCG_ADD: u8 = 0xD;
|
||||||
const OPCG_SHIFT: u8 = 0xE;
|
const OPCG_SHIFT: u8 = 0xE;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
const OPCG_RESERVED1: u8 = 0xA;
|
||||||
|
#[allow(dead_code)]
|
||||||
const OPCG_RESERVED2: u8 = 0xF;
|
const OPCG_RESERVED2: u8 = 0xF;
|
||||||
|
|
||||||
|
|
||||||
@@ -236,7 +239,7 @@ impl M68kDecoder {
|
|||||||
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
|
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
|
||||||
0b0001 => Ok(Instruction::ANDtoCCR(data as u8)),
|
0b0001 => Ok(Instruction::ANDtoCCR(data as u8)),
|
||||||
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
|
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0b01 => {
|
0b01 => {
|
||||||
@@ -245,10 +248,10 @@ impl M68kDecoder {
|
|||||||
0b0000 => Ok(Instruction::ORtoSR(data)),
|
0b0000 => Ok(Instruction::ORtoSR(data)),
|
||||||
0b0010 => Ok(Instruction::ANDtoSR(data)),
|
0b0010 => Ok(Instruction::ANDtoSR(data)),
|
||||||
0b1010 => Ok(Instruction::EORtoSR(data)),
|
0b1010 => Ok(Instruction::EORtoSR(data)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
} else if (ins & 0x138) == 0x108 {
|
} else if (ins & 0x138) == 0x108 {
|
||||||
let dreg = get_high_reg(ins);
|
let dreg = get_high_reg(ins);
|
||||||
@@ -275,7 +278,7 @@ impl M68kDecoder {
|
|||||||
0b01 => Ok(Instruction::BCHG(bitnum, target, size)),
|
0b01 => Ok(Instruction::BCHG(bitnum, target, size)),
|
||||||
0b10 => Ok(Instruction::BCLR(bitnum, target, size)),
|
0b10 => Ok(Instruction::BCLR(bitnum, target, size)),
|
||||||
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
|
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let size = get_size(ins);
|
let size = get_size(ins);
|
||||||
@@ -283,7 +286,7 @@ impl M68kDecoder {
|
|||||||
Some(Size::Byte) => (self.read_instruction_word(system)? as u32 & 0xFF),
|
Some(Size::Byte) => (self.read_instruction_word(system)? as u32 & 0xFF),
|
||||||
Some(Size::Word) => self.read_instruction_word(system)? as u32,
|
Some(Size::Word) => self.read_instruction_word(system)? as u32,
|
||||||
Some(Size::Long) => self.read_instruction_long(system)?,
|
Some(Size::Long) => self.read_instruction_long(system)?,
|
||||||
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
let target = self.decode_lower_effective_address(system, ins, size)?;
|
let target = self.decode_lower_effective_address(system, ins, size)?;
|
||||||
|
|
||||||
@@ -294,7 +297,7 @@ impl M68kDecoder {
|
|||||||
0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())),
|
0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())),
|
||||||
0b1010 => Ok(Instruction::EOR(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())),
|
0b1100 => Ok(Instruction::CMP(Target::Immediate(data), target, size.unwrap())),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -330,7 +333,7 @@ impl M68kDecoder {
|
|||||||
let size = match get_size(ins) {
|
let size = match get_size(ins) {
|
||||||
Some(Size::Word) => Size::Word,
|
Some(Size::Word) => Size::Word,
|
||||||
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
@@ -362,7 +365,7 @@ impl M68kDecoder {
|
|||||||
match get_size(ins) {
|
match get_size(ins) {
|
||||||
Some(size) => Ok(Instruction::CLR(target, size)),
|
Some(size) => Ok(Instruction::CLR(target, size)),
|
||||||
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
|
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
|
||||||
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0b100 => {
|
0b100 => {
|
||||||
@@ -377,7 +380,7 @@ impl M68kDecoder {
|
|||||||
None => Ok(Instruction::MOVEtoSR(target)),
|
None => Ok(Instruction::MOVEtoSR(target)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
} else if ins_0f00 == 0x800 {
|
} else if ins_0f00 == 0x800 {
|
||||||
let subselect = (ins & 0x01C0) >> 6;
|
let subselect = (ins & 0x01C0) >> 6;
|
||||||
@@ -402,7 +405,7 @@ impl M68kDecoder {
|
|||||||
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
||||||
Ok(Instruction::EXT(get_low_reg(ins), size))
|
Ok(Instruction::EXT(get_low_reg(ins), size))
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
} else if ins_0f00 == 0xA00 {
|
} else if ins_0f00 == 0xA00 {
|
||||||
if (ins & 0x0FF) == 0xFC {
|
if (ins & 0x0FF) == 0xFC {
|
||||||
@@ -461,15 +464,15 @@ impl M68kDecoder {
|
|||||||
};
|
};
|
||||||
let creg = match ins2 & 0xFFF {
|
let creg = match ins2 & 0xFFF {
|
||||||
0x801 => ControlRegister::VBR,
|
0x801 => ControlRegister::VBR,
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
Ok(Instruction::MOVEC(target, creg, dir))
|
Ok(Instruction::MOVEC(target, creg, dir))
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
|
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_ADDQ_SUBQ => {
|
OPCG_ADDQ_SUBQ => {
|
||||||
@@ -518,7 +521,7 @@ impl M68kDecoder {
|
|||||||
},
|
},
|
||||||
OPCG_MOVEQ => {
|
OPCG_MOVEQ => {
|
||||||
if (ins & 0x0100) != 0 {
|
if (ins & 0x0100) != 0 {
|
||||||
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
|
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
|
||||||
}
|
}
|
||||||
let reg = get_high_reg(ins);
|
let reg = get_high_reg(ins);
|
||||||
let data = (ins & 0xFF) as u8;
|
let data = (ins & 0xFF) as u8;
|
||||||
@@ -596,7 +599,7 @@ impl M68kDecoder {
|
|||||||
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
|
||||||
Ok(Instruction::CMPA(target, reg, size))
|
Ok(Instruction::CMPA(target, reg, size))
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OPCG_MUL_AND => {
|
OPCG_MUL_AND => {
|
||||||
@@ -617,7 +620,7 @@ impl M68kDecoder {
|
|||||||
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
|
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
|
||||||
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
|
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
|
||||||
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
|
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
} else if size.is_none() {
|
} else if size.is_none() {
|
||||||
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
|
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
|
||||||
@@ -675,7 +678,7 @@ impl M68kDecoder {
|
|||||||
0b01 => Ok(Instruction::LSd(count, Target::DirectDReg(reg), size, dir)),
|
0b01 => Ok(Instruction::LSd(count, Target::DirectDReg(reg), size, dir)),
|
||||||
0b10 => Ok(Instruction::ROXd(count, Target::DirectDReg(reg), size, dir)),
|
0b10 => Ok(Instruction::ROXd(count, Target::DirectDReg(reg), size, dir)),
|
||||||
0b11 => Ok(Instruction::ROd(count, Target::DirectDReg(reg), size, dir)),
|
0b11 => Ok(Instruction::ROd(count, Target::DirectDReg(reg), size, dir)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
@@ -687,12 +690,12 @@ impl M68kDecoder {
|
|||||||
0b01 => Ok(Instruction::LSd(count, target, Size::Word, dir)),
|
0b01 => Ok(Instruction::LSd(count, target, Size::Word, dir)),
|
||||||
0b10 => Ok(Instruction::ROXd(count, target, Size::Word, dir)),
|
0b10 => Ok(Instruction::ROXd(count, target, Size::Word, dir)),
|
||||||
0b11 => Ok(Instruction::ROd(count, target, Size::Word, dir)),
|
0b11 => Ok(Instruction::ROd(count, target, Size::Word, dir)),
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,7 +745,7 @@ impl M68kDecoder {
|
|||||||
|
|
||||||
panic!("Not Implemented");
|
panic!("Not Implemented");
|
||||||
} else {
|
} else {
|
||||||
Err(Error::processor(ERR_ILLEGAL_INSTRUCTION))
|
Err(Error::processor(Exceptions::IllegalInstruction as u32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,18 +784,47 @@ impl M68kDecoder {
|
|||||||
let data = match size {
|
let data = match size {
|
||||||
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(system)? as u32,
|
Some(Size::Byte) | Some(Size::Word) => self.read_instruction_word(system)? as u32,
|
||||||
Some(Size::Long) => self.read_instruction_long(system)?,
|
Some(Size::Long) => self.read_instruction_long(system)?,
|
||||||
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
Target::Immediate(data)
|
Target::Immediate(data)
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
|
||||||
};
|
};
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dump_disassembly(&mut self, system: &System, start: u32, length: u32) {
|
||||||
|
let mut next = start;
|
||||||
|
while next < (start + length) {
|
||||||
|
match self.decode_at(&system, next) {
|
||||||
|
Ok(()) => {
|
||||||
|
self.dump_decoded(system);
|
||||||
|
next = self.end;
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
println!("{:?}", err);
|
||||||
|
match err {
|
||||||
|
Error { native, .. } if native == Exceptions::IllegalInstruction as u32 => {
|
||||||
|
println!(" at {:08x}: {:04x}", self.start, system.get_bus().read_beu16(self.start as Address).unwrap());
|
||||||
|
},
|
||||||
|
_ => { },
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump_decoded(&mut self, system: &System) {
|
||||||
|
let ins_data: Result<String, Error> =
|
||||||
|
(0..((self.end - self.start) / 2)).map(|offset|
|
||||||
|
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.start + (offset * 2)) as Address).unwrap()))
|
||||||
|
).collect();
|
||||||
|
debug!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@@ -5,7 +5,6 @@ use crate::memory::{Address, Addressable};
|
|||||||
use crate::devices::{Clock, Steppable, Interruptable};
|
use crate::devices::{Clock, Steppable, Interruptable};
|
||||||
|
|
||||||
use super::decode::{
|
use super::decode::{
|
||||||
M68kDecoder,
|
|
||||||
Instruction,
|
Instruction,
|
||||||
Target,
|
Target,
|
||||||
Size,
|
Size,
|
||||||
@@ -18,7 +17,7 @@ use super::decode::{
|
|||||||
sign_extend_to_long
|
sign_extend_to_long
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::state::{M68k, Status, Flags, InterruptPriority};
|
use super::state::{M68k, Status, Flags, Exceptions, InterruptPriority};
|
||||||
|
|
||||||
impl Steppable for M68k {
|
impl Steppable for M68k {
|
||||||
fn step(&mut self, system: &System) -> Result<Clock, Error> {
|
fn step(&mut self, system: &System) -> Result<Clock, Error> {
|
||||||
@@ -50,24 +49,15 @@ impl Interruptable for M68k {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl M68k {
|
impl M68k {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn is_running(&self) -> bool {
|
pub fn is_running(&self) -> bool {
|
||||||
self.state.status != Status::Stopped
|
self.state.status != Status::Stopped
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self, system: &System) -> Result<(), Error> {
|
|
||||||
println!("Initializing CPU");
|
|
||||||
|
|
||||||
self.state.msp = system.get_bus().read_beu32(0)?;
|
|
||||||
self.state.pc = system.get_bus().read_beu32(4)?;
|
|
||||||
self.state.status = Status::Running;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
|
pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
|
||||||
match self.state.status {
|
match self.state.status {
|
||||||
Status::Init => self.init(system),
|
Status::Init => self.init(system),
|
||||||
Status::Stopped | Status::Halted => Err(Error::new("CPU stopped")),
|
Status::Stopped => Err(Error::new("CPU stopped")),
|
||||||
Status::Running => {
|
Status::Running => {
|
||||||
let timer = self.timer.cycle.start();
|
let timer = self.timer.cycle.start();
|
||||||
self.decode_next(system)?;
|
self.decode_next(system)?;
|
||||||
@@ -85,6 +75,13 @@ impl M68k {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn init(&mut self, system: &System) -> Result<(), Error> {
|
||||||
|
self.state.msp = system.get_bus().read_beu32(0)?;
|
||||||
|
self.state.pc = system.get_bus().read_beu32(4)?;
|
||||||
|
self.state.status = Status::Running;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), Error> {
|
pub fn check_pending_interrupts(&mut self, system: &System) -> Result<(), Error> {
|
||||||
let current_ipl = self.state.current_ipl as u8;
|
let current_ipl = self.state.current_ipl as u8;
|
||||||
let pending_ipl = self.state.pending_ipl as u8;
|
let pending_ipl = self.state.pending_ipl as u8;
|
||||||
@@ -126,12 +123,7 @@ impl M68k {
|
|||||||
self.timer.decode.end(timer);
|
self.timer.decode.end(timer);
|
||||||
|
|
||||||
if self.debugger.use_tracing {
|
if self.debugger.use_tracing {
|
||||||
// Print instruction bytes for debugging
|
self.decoder.dump_decoded(system);
|
||||||
let ins_data: Result<String, Error> =
|
|
||||||
(0..((self.decoder.end - self.decoder.start) / 2)).map(|offset|
|
|
||||||
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.decoder.start + (offset * 2)) as Address)?))
|
|
||||||
).collect();
|
|
||||||
debug!("{:#010x}: {}\n\t{:?}\n", self.decoder.start, ins_data?, self.decoder.instruction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.debugger.use_debugger {
|
if self.debugger.use_debugger {
|
||||||
@@ -259,6 +251,11 @@ impl M68k {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let value = self.get_target_value(system, src, size)?;
|
let value = self.get_target_value(system, src, size)?;
|
||||||
|
if value == 0 {
|
||||||
|
self.exception(system, Exceptions::ZeroDivide as u8)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let existing = self.get_target_value(system, dest, Size::Long)?;
|
let existing = self.get_target_value(system, dest, Size::Long)?;
|
||||||
let result = match sign {
|
let result = match sign {
|
||||||
Sign::Signed => {
|
Sign::Signed => {
|
||||||
@@ -537,7 +534,7 @@ impl M68k {
|
|||||||
},
|
},
|
||||||
Instruction::TRAPV => {
|
Instruction::TRAPV => {
|
||||||
if self.get_flag(Flags::Overflow) {
|
if self.get_flag(Flags::Overflow) {
|
||||||
self.exception(system, 7)?;
|
self.exception(system, Exceptions::TrapvInstruction as u8)?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Instruction::UNLK(reg) => {
|
Instruction::UNLK(reg) => {
|
||||||
|
@@ -9,9 +9,13 @@ use super::debugger::M68kDebugger;
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum M68kType {
|
pub enum M68kType {
|
||||||
|
#[allow(dead_code)]
|
||||||
MC68000,
|
MC68000,
|
||||||
|
#[allow(dead_code)]
|
||||||
MC68010,
|
MC68010,
|
||||||
|
#[allow(dead_code)]
|
||||||
MC68020,
|
MC68020,
|
||||||
|
#[allow(dead_code)]
|
||||||
MC68030,
|
MC68030,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,9 +35,17 @@ pub enum Flags {
|
|||||||
Tracing = 0x8000,
|
Tracing = 0x8000,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ERR_BUS_ERROR: u32 = 2;
|
#[repr(u8)]
|
||||||
pub const ERR_ADDRESS_ERROR: u32 = 3;
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
|
pub enum Exceptions {
|
||||||
|
BusError = 2,
|
||||||
|
AddressError = 3,
|
||||||
|
IllegalInstruction = 4,
|
||||||
|
ZeroDivide = 5,
|
||||||
|
ChkInstruction = 6,
|
||||||
|
TrapvInstruction = 7,
|
||||||
|
PrivilegeViolation = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
@@ -41,7 +53,6 @@ pub enum Status {
|
|||||||
Init,
|
Init,
|
||||||
Running,
|
Running,
|
||||||
Stopped,
|
Stopped,
|
||||||
Halted,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@@ -72,6 +83,7 @@ impl InterruptPriority {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct M68kState {
|
pub struct M68kState {
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
pub current_ipl: InterruptPriority,
|
pub current_ipl: InterruptPriority,
|
||||||
@@ -127,6 +139,7 @@ impl M68k {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.state = M68kState::new();
|
self.state = M68kState::new();
|
||||||
self.decoder = M68kDecoder::new(self.cputype, 0, 0);
|
self.decoder = M68kDecoder::new(self.cputype, 0, 0);
|
||||||
|
@@ -7,8 +7,6 @@ use crate::memory::{Address, Addressable};
|
|||||||
use crate::devices::{Clock, Steppable};
|
use crate::devices::{Clock, Steppable};
|
||||||
|
|
||||||
|
|
||||||
const ATA_REG_DEV_CONTROL: Address = 0x1D;
|
|
||||||
const ATA_REG_DEV_ADDRESS: Address = 0x1F;
|
|
||||||
const ATA_REG_DATA_WORD: Address = 0x20;
|
const ATA_REG_DATA_WORD: Address = 0x20;
|
||||||
const ATA_REG_DATA_BYTE: Address = 0x21;
|
const ATA_REG_DATA_BYTE: Address = 0x21;
|
||||||
const ATA_REG_FEATURE: Address = 0x23;
|
const ATA_REG_FEATURE: Address = 0x23;
|
||||||
@@ -26,8 +24,11 @@ const ATA_CMD_WRITE_SECTORS: u8 = 0x30;
|
|||||||
const ATA_CMD_IDENTIFY: u8 = 0xEC;
|
const ATA_CMD_IDENTIFY: u8 = 0xEC;
|
||||||
const ATA_CMD_SET_FEATURE: u8 = 0xEF;
|
const ATA_CMD_SET_FEATURE: u8 = 0xEF;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
const ATA_ST_BUSY: u8 = 0x80;
|
const ATA_ST_BUSY: u8 = 0x80;
|
||||||
|
#[allow(dead_code)]
|
||||||
const ATA_ST_DATA_READY: u8 = 0x08;
|
const ATA_ST_DATA_READY: u8 = 0x08;
|
||||||
|
#[allow(dead_code)]
|
||||||
const ATA_ST_ERROR: u8 = 0x01;
|
const ATA_ST_ERROR: u8 = 0x01;
|
||||||
|
|
||||||
const ATA_SECTOR_SIZE: u32 = 512;
|
const ATA_SECTOR_SIZE: u32 = 512;
|
||||||
@@ -37,6 +38,7 @@ const DEV_NAME: &'static str = "ata";
|
|||||||
pub struct AtaDevice {
|
pub struct AtaDevice {
|
||||||
pub selected_sector: u32,
|
pub selected_sector: u32,
|
||||||
pub selected_count: u32,
|
pub selected_count: u32,
|
||||||
|
pub last_error: u8,
|
||||||
pub contents: Vec<u8>,
|
pub contents: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +48,7 @@ impl AtaDevice {
|
|||||||
AtaDevice {
|
AtaDevice {
|
||||||
selected_sector: 0,
|
selected_sector: 0,
|
||||||
selected_count: 0,
|
selected_count: 0,
|
||||||
|
last_error: 0,
|
||||||
contents: vec![],
|
contents: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +95,9 @@ impl Addressable for AtaDevice {
|
|||||||
ATA_REG_STATUS => {
|
ATA_REG_STATUS => {
|
||||||
data[0] = ATA_ST_DATA_READY;
|
data[0] = ATA_ST_DATA_READY;
|
||||||
},
|
},
|
||||||
|
ATA_REG_ERROR => {
|
||||||
|
data[0] = self.last_error;
|
||||||
|
},
|
||||||
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); },
|
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,13 +45,21 @@ const REG_IVR_WR: Address = 0x19;
|
|||||||
|
|
||||||
|
|
||||||
// Status Register Bits (SRA/SRB)
|
// Status Register Bits (SRA/SRB)
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_RECEIVED_BREAK: u8 = 0x80;
|
const SR_RECEIVED_BREAK: u8 = 0x80;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_FRAMING_ERROR: u8 = 0x40;
|
const SR_FRAMING_ERROR: u8 = 0x40;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_PARITY_ERROR: u8 = 0x20;
|
const SR_PARITY_ERROR: u8 = 0x20;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_OVERRUN_ERROR: u8 = 0x10;
|
const SR_OVERRUN_ERROR: u8 = 0x10;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_TX_EMPTY: u8 = 0x08;
|
const SR_TX_EMPTY: u8 = 0x08;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_TX_READY: u8 = 0x04;
|
const SR_TX_READY: u8 = 0x04;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_RX_FULL: u8 = 0x02;
|
const SR_RX_FULL: u8 = 0x02;
|
||||||
|
#[allow(dead_code)]
|
||||||
const SR_RX_READY: u8 = 0x01;
|
const SR_RX_READY: u8 = 0x01;
|
||||||
|
|
||||||
|
|
||||||
@@ -160,6 +168,11 @@ pub struct MC68681 {
|
|||||||
pub timer_preload: u16,
|
pub timer_preload: u16,
|
||||||
pub timer_count: u16,
|
pub timer_count: u16,
|
||||||
pub is_timing: bool,
|
pub is_timing: bool,
|
||||||
|
|
||||||
|
pub input_pin_change: u8,
|
||||||
|
pub input_state: u8,
|
||||||
|
pub output_conf: u8,
|
||||||
|
pub output_state: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MC68681 {
|
impl MC68681 {
|
||||||
@@ -176,6 +189,11 @@ impl MC68681 {
|
|||||||
timer_preload: 0,
|
timer_preload: 0,
|
||||||
timer_count: 0,
|
timer_count: 0,
|
||||||
is_timing: true,
|
is_timing: true,
|
||||||
|
|
||||||
|
input_pin_change: 0,
|
||||||
|
input_state: 0,
|
||||||
|
output_conf: 0,
|
||||||
|
output_state: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +265,12 @@ impl Addressable for MC68681 {
|
|||||||
REG_ISR_RD => {
|
REG_ISR_RD => {
|
||||||
data[0] = self.int_status;
|
data[0] = self.int_status;
|
||||||
},
|
},
|
||||||
|
REG_IPCR_RD => {
|
||||||
|
data[0] = self.input_pin_change;
|
||||||
|
},
|
||||||
|
REG_INPUT_RD => {
|
||||||
|
data[0] = self.input_state;
|
||||||
|
},
|
||||||
REG_START_RD => {
|
REG_START_RD => {
|
||||||
self.timer_count = self.timer_preload;
|
self.timer_count = self.timer_preload;
|
||||||
self.is_timing = true;
|
self.is_timing = true;
|
||||||
@@ -271,9 +295,9 @@ impl Addressable for MC68681 {
|
|||||||
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
||||||
println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr);
|
println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr);
|
||||||
match addr {
|
match addr {
|
||||||
//REG_MR1A_MR2A | REG_ACR_WR => {
|
REG_MR1A_MR2A | REG_MR1B_MR2B | REG_CSRA_WR | REG_CSRB_WR => {
|
||||||
// // TODO config
|
// NOTE we aren't simulating the serial speeds, so we aren't doing anything with these settings atm
|
||||||
//},
|
},
|
||||||
REG_ACR_WR => {
|
REG_ACR_WR => {
|
||||||
self.acr = data[0];
|
self.acr = data[0];
|
||||||
}
|
}
|
||||||
@@ -309,6 +333,15 @@ impl Addressable for MC68681 {
|
|||||||
REG_IVR_WR => {
|
REG_IVR_WR => {
|
||||||
self.int_vector = data[0];
|
self.int_vector = data[0];
|
||||||
},
|
},
|
||||||
|
REG_OPCR_WR => {
|
||||||
|
self.output_conf = data[0];
|
||||||
|
},
|
||||||
|
REG_OUT_SET => {
|
||||||
|
self.output_state |= data[0];
|
||||||
|
},
|
||||||
|
REG_OUT_RESET => {
|
||||||
|
self.output_state &= !data[0];
|
||||||
|
},
|
||||||
_ => { },
|
_ => { },
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Reference in New Issue
Block a user