Reorganized decode and add some support for other m68k processors

This commit is contained in:
transistor 2021-10-10 14:26:54 -07:00
parent b588563acc
commit 94141e112e
8 changed files with 252 additions and 160 deletions

View File

@ -3,7 +3,7 @@ use crate::error::Error;
use crate::system::System;
use crate::memory::{Address, Addressable};
use super::state::MC68010;
use super::state::M68k;
pub struct StackTracer {
pub calls: Vec<u32>,
@ -46,7 +46,7 @@ impl M68kDebugger {
}
}
impl MC68010 {
impl M68k {
pub fn enable_tracing(&mut self) {
self.debugger.use_tracing = true;
}

View File

@ -6,7 +6,7 @@ use crate::system::System;
use crate::memory::Address;
use crate::devices::AddressableDeviceRefMut;
use super::state::ERR_ILLEGAL_INSTRUCTION;
use super::state::{M68kType, ERR_ILLEGAL_INSTRUCTION};
const OPCG_BIT_OPS: u8 = 0x0;
@ -107,14 +107,16 @@ pub enum Instruction {
ANDtoSR(u16),
ASd(Target, Target, Size, ShiftDirection),
Bcc(Condition, i16),
BRA(i16),
BSR(i16),
BTST(Target, Target, Size),
Bcc(Condition, i32),
BRA(i32),
BSR(i32),
BCHG(Target, Target, Size),
BCLR(Target, Target, Size),
BSET(Target, Target, Size),
BTST(Target, Target, Size),
BKPT(u8),
CHK(Target, u8, Size),
CLR(Target, Size),
CMP(Target, Target, Size),
CMPA(Target, u8, Size),
@ -141,11 +143,13 @@ pub enum Instruction {
MOVEA(Target, u8, Size),
MOVEfromSR(Target),
MOVEtoSR(Target),
MOVEfromCCR(Target),
MOVEtoCCR(Target),
MOVEC(Target, ControlRegister, Direction),
MOVEUSP(Target, Direction),
MOVEM(Target, Size, Direction, u16),
MOVEP(u8, Target, Size, Direction),
MOVEQ(u8, u8),
MOVEUSP(Target, Direction),
MUL(Target, Target, Size, Sign),
NBCD(Target),
@ -167,6 +171,7 @@ pub enum Instruction {
RTE,
RTR,
RTS,
RTD(i16),
//SBCD
Scc(Condition, Target),
@ -184,6 +189,7 @@ pub enum Instruction {
pub struct M68kDecoder {
pub cputype: M68kType,
pub base: u32,
pub start: u32,
pub end: u32,
@ -191,8 +197,9 @@ pub struct M68kDecoder {
}
impl M68kDecoder {
pub fn new(base: u32, start: u32) -> M68kDecoder {
pub fn new(cputype: M68kType, base: u32, start: u32) -> M68kDecoder {
M68kDecoder {
cputype,
base: base,
start: start,
end: start,
@ -200,11 +207,18 @@ impl M68kDecoder {
}
}
pub fn decode_at(system: &System, start: u32) -> Result<M68kDecoder, Error> {
#[inline(always)]
pub fn init(&mut self, base: u32, start: u32) {
self.base = base;
self.start = start;
self.end = start;
}
pub fn decode_at(&mut self, system: &System, start: u32) -> Result<(), Error> {
let (memory, relative_addr) = system.get_bus().get_device_at(start as Address, 12)?;
let mut decoder = M68kDecoder::new(start - relative_addr as u32, start);
decoder.instruction = decoder.decode_one(&mut memory.borrow_mut())?;
Ok(decoder)
self.init(start - relative_addr as u32, start);
self.instruction = self.decode_one(&mut memory.borrow_mut())?;
Ok(())
}
pub fn decode_one(&mut self, system: &mut AddressableDeviceRefMut<'_>) -> Result<Instruction, Error> {
@ -236,6 +250,13 @@ impl M68kDecoder {
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0x138) == 0x108 {
let dreg = get_high_reg(ins);
let areg = get_low_reg(ins);
let dir = if (ins & 0x0800) == 0 { Direction::FromTarget } else { Direction::ToTarget };
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
let offset = sign_extend_to_long(self.read_instruction_word(system)? as u32, Size::Word);
Ok(Instruction::MOVEP(dreg, Target::IndirectARegOffset(areg, offset), size, dir))
} else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 {
let bitnum = if (ins & 0x0100) == 0x0100 {
Target::DirectDReg(get_high_reg(ins))
@ -256,7 +277,6 @@ impl M68kDecoder {
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else {
let size = get_size(ins);
let data = match size {
@ -302,14 +322,34 @@ impl M68kDecoder {
}
},
OPCG_MISC => {
if (ins & 0b000101000000) == 0b000100000000 {
// CHK Instruction
panic!("Not Implemented");
} else if (ins & 0b000111000000) == 0b000111000000 {
let src = self.decode_lower_effective_address(system, ins, None)?;
let dest = get_high_reg(ins);
Ok(Instruction::LEA(src, dest))
} else if (ins & 0b100000000000) == 0b000000000000 {
let ins_0f00 = ins & 0xF00;
let ins_00f0 = ins & 0x0F0;
if (ins & 0x180) == 0x180 {
if (ins & 0x040) == 0 {
let size = match get_size(ins) {
Some(Size::Word) => Size::Word,
Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long,
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
};
let reg = get_high_reg(ins);
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::CHK(target, reg, size))
} else {
let src = self.decode_lower_effective_address(system, ins, None)?;
let dest = get_high_reg(ins);
Ok(Instruction::LEA(src, dest))
}
} else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 {
let mode = get_low_mode(ins);
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
let data = self.read_instruction_word(system)?;
let target = self.decode_lower_effective_address(system, ins, None)?;
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data))
} else if (ins & 0x800) == 0 {
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
match (ins & 0x0700) >> 8 {
0b000 => {
@ -321,6 +361,7 @@ impl M68kDecoder {
0b010 => {
match get_size(ins) {
Some(size) => Ok(Instruction::CLR(target, size)),
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
None => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
},
@ -338,19 +379,7 @@ impl M68kDecoder {
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0b101110000000) == 0b100010000000 {
let mode = get_low_mode(ins);
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
if mode == 0b000 {
Ok(Instruction::EXT(get_low_reg(ins), size))
} else {
let data = self.read_instruction_word(system)?;
let target = self.decode_lower_effective_address(system, ins, None)?;
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data))
}
} else if (ins & 0b111100000000) == 0b100000000000 {
} else if ins_0f00 == 0x800 {
let subselect = (ins & 0x01C0) >> 6;
let mode = get_low_mode(ins);
match (subselect, mode) {
@ -361,67 +390,86 @@ impl M68kDecoder {
(0b001, 0b000) => {
Ok(Instruction::SWAP(get_low_reg(ins)))
},
(0b001, 0b001) => {
Ok(Instruction::BKPT(get_low_reg(ins)))
},
(0b001, _) => {
let target = self.decode_lower_effective_address(system, ins, None)?;
Ok(Instruction::PEA(target))
},
(0b010, 0b000) |
(0b011, 0b000) => {
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
Ok(Instruction::EXT(get_low_reg(ins), size))
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0b111100000000) == 0b101000000000 {
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
match get_size(ins) {
Some(size) => Ok(Instruction::TST(target, size)),
None => Ok(Instruction::TAS(target)),
}
} else if (ins & 0b111110000000) == 0b111010000000 {
let target = self.decode_lower_effective_address(system, ins, None)?;
if (ins & 0b01000000) == 0 {
Ok(Instruction::JSR(target))
} else if ins_0f00 == 0xA00 {
if (ins & 0x0FF) == 0xFC {
Ok(Instruction::ILLEGAL)
} else {
Ok(Instruction::JMP(target))
let target = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
match get_size(ins) {
Some(size) => Ok(Instruction::TST(target, size)),
None => Ok(Instruction::TAS(target)),
}
}
} else if (ins & 0b111111110000) == 0b111001000000 {
Ok(Instruction::TRAP((ins & 0x000F) as u8))
} else if (ins & 0b111111110000) == 0b111001010000 {
let reg = get_low_reg(ins);
if (ins & 0b1000) == 0 {
let data = self.read_instruction_word(system)?;
Ok(Instruction::LINK(reg, data as i16))
} else {
Ok(Instruction::UNLK(reg))
}
} else if (ins & 0b111111110000) == 0b111001100000 {
let reg = get_low_reg(ins);
let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget };
Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir))
} else {
match ins & 0x0FFF {
0xAFC => Ok(Instruction::ILLEGAL),
0xE70 => Ok(Instruction::RESET),
0xE71 => Ok(Instruction::NOP),
0xE72 => {
} else if ins_0f00 == 0xE00 {
if (ins & 0x80) == 0x80 {
let target = self.decode_lower_effective_address(system, ins, None)?;
if (ins & 0b01000000) == 0 {
Ok(Instruction::JSR(target))
} else {
Ok(Instruction::JMP(target))
}
} else if ins_00f0 == 0x40 {
Ok(Instruction::TRAP((ins & 0x000F) as u8))
} else if ins_00f0 == 0x50 {
let reg = get_low_reg(ins);
if (ins & 0b1000) == 0 {
let data = self.read_instruction_word(system)?;
Ok(Instruction::STOP(data))
},
0xE73 => Ok(Instruction::RTE),
0xE75 => Ok(Instruction::RTS),
0xE76 => Ok(Instruction::TRAPV),
0xE77 => Ok(Instruction::RTR),
0xE7A | 0xE7B => {
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
let ins2 = self.read_instruction_word(system)?;
let target = match ins2 & 0x8000 {
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
};
let creg = match ins2 & 0xFFF {
0x801 => ControlRegister::VBR,
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
};
Ok(Instruction::MOVEC(target, creg, dir))
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
Ok(Instruction::LINK(reg, data as i16))
} else {
Ok(Instruction::UNLK(reg))
}
} else if ins_00f0 == 0x60 {
let reg = get_low_reg(ins);
let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget };
Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir))
} else {
match ins & 0x00FF {
0x70 => Ok(Instruction::RESET),
0x71 => Ok(Instruction::NOP),
0x72 => {
let data = self.read_instruction_word(system)?;
Ok(Instruction::STOP(data))
},
0x73 => Ok(Instruction::RTE),
0x74 if self.cputype >= M68kType::MC68010 => {
let offset = self.read_instruction_word(system)? as i16;
Ok(Instruction::RTD(offset))
},
0x75 => Ok(Instruction::RTS),
0x76 => Ok(Instruction::TRAPV),
0x77 => Ok(Instruction::RTR),
0x7A | 0x7B if self.cputype >= M68kType::MC68010 => {
let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget };
let ins2 = self.read_instruction_word(system)?;
let target = match ins2 & 0x8000 {
0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8),
_ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8),
};
let creg = match ins2 & 0xFFF {
0x801 => ControlRegister::VBR,
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
};
Ok(Instruction::MOVEC(target, creg, dir))
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
}
} else {
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
}
},
OPCG_ADDQ_SUBQ => {
@ -455,9 +503,11 @@ impl M68kDecoder {
}
},
OPCG_BRANCH => {
let mut disp = ((ins & 0xFF) as i8) as i16;
let mut disp = ((ins & 0xFF) as i8) as i32;
if disp == 0 {
disp = self.read_instruction_word(system)? as i16;
disp = (self.read_instruction_word(system)? as i16) as i32;
} else if disp == 0xff && self.cputype >= M68kType::MC68020 {
disp = self.read_instruction_long(system)? as i32;
}
let condition = get_condition(ins);
match condition {
@ -467,7 +517,9 @@ impl M68kDecoder {
}
},
OPCG_MOVEQ => {
// TODO make sure the 9th bit is 0
if (ins & 0x0100) != 0 {
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
}
let reg = get_high_reg(ins);
let data = (ins & 0xFF) as u8;
Ok(Instruction::MOVEQ(data, reg))
@ -491,17 +543,21 @@ impl M68kDecoder {
}
},
OPCG_SUB => {
// TODO need to decode the SUBX instruction (would likely be erroneously decoded atm)
let reg = get_high_reg(ins);
let dir = (ins & 0x0100) >> 8;
let size = get_size(ins);
match size {
Some(size) => {
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
if (ins & 0b100110000) == 0b100000000 {
// TODO implement SUBX
panic!("Not Implemented");
} else {
Ok(Instruction::SUB(Target::DirectDReg(reg), target, size))
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::SUB(target, Target::DirectDReg(reg), size))
} else {
Ok(Instruction::SUB(Target::DirectDReg(reg), target, size))
}
}
},
None => {
@ -517,9 +573,12 @@ impl M68kDecoder {
let size = get_size(ins);
match (optype, size) {
(0b1, Some(size)) => {
// TODO need to decode the CMPM instruction (mode == 0b001) (would likely be erroneously decoded atm)
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
if get_low_mode(ins) == 0b001 {
Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size))
} else {
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
Ok(Instruction::EOR(Target::DirectDReg(reg), target, size))
}
},
(0b0, Some(size)) => {
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
@ -536,14 +595,23 @@ impl M68kDecoder {
OPCG_MUL_AND => {
let size = get_size(ins);
if size.is_none() {
if (ins & 0b000111110000) == 0b000100000000 {
// TODO ABCD
panic!("Not Implemented");
} else if (ins & 0b000100110000) == 0b000100000000 {
let regx = get_high_reg(ins);
let regy = get_low_reg(ins);
match (ins & 0x00F8) >> 3 {
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))),
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if size.is_none() {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(system, ins, Some(Size::Word))?;
Ok(Instruction::MUL(effective_addr, data_reg, Size::Word, sign))
} else if (ins & 0b000111110000) == 0b000100000000 {
// TODO ABCD or EXG
panic!("Not Implemented");
} else {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(system, ins, size)?;
@ -552,17 +620,21 @@ impl M68kDecoder {
}
},
OPCG_ADD => {
// TODO need to decode the ADDX instruction (would likely be erroneously decoded atm)
let reg = get_high_reg(ins);
let dir = (ins & 0x0100) >> 8;
let size = get_size(ins);
match size {
Some(size) => {
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
if (ins & 0b100110000) == 0b100000000 {
// TODO implement ADDX
panic!("Not Implemented");
} else {
Ok(Instruction::ADD(Target::DirectDReg(reg), target, size))
let target = self.decode_lower_effective_address(system, ins, Some(size))?;
if dir == 0 {
Ok(Instruction::ADD(target, Target::DirectDReg(reg), size))
} else {
Ok(Instruction::ADD(Target::DirectDReg(reg), target, size))
}
}
},
None => {
@ -636,14 +708,28 @@ impl M68kDecoder {
self.get_mode_as_target(system, mode, reg, size)
}
fn decode_brief_extension_word(&self, brief_extension: u16) -> (RegisterType, u8, i32, Size) {
let data = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
fn decode_extension_word(&mut self, system: &mut AddressableDeviceRefMut<'_>, areg: Option<u8>) -> Result<Target, Error> {
let brief_extension = self.read_instruction_word(system)?;
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
let xreg = ((brief_extension & 0x7000) >> 12) as u8;
let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long };
let use_full = (brief_extension & 0x0100) == 1;
let scale = (brief_extension & 0x0600) >> 9 as u8;
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
if !use_full {
let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
match areg {
Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, rtype, xreg, displacement, size)),
None => Ok(Target::IndirectPCXRegOffset(rtype, xreg, displacement, size)),
}
} else if self.cputype >= M68kType::MC68020 {
let use_base = (brief_extension & 0x0080) == 0;
let use_index = (brief_extension & 0x0040) == 0;
(rtype, xreg, data, size)
panic!("Not Implemented");
} else {
Err(Error::processor(ERR_ILLEGAL_INSTRUCTION))
}
}
pub fn get_mode_as_target(&mut self, system: &mut AddressableDeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
@ -658,9 +744,7 @@ impl M68kDecoder {
Target::IndirectARegOffset(reg, data)
},
0b110 => {
let brief_extension = self.read_instruction_word(system)?;
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
Target::IndirectARegXRegOffset(reg, rtype, xreg, data, size)
self.decode_extension_word(system, Some(reg))?
},
0b111 => {
match reg {
@ -677,9 +761,7 @@ impl M68kDecoder {
Target::IndirectPCOffset(data)
},
0b011 => {
let brief_extension = self.read_instruction_word(system)?;
let (rtype, xreg, data, size) = self.decode_brief_extension_word(brief_extension);
Target::IndirectPCXRegOffset(rtype, xreg, data, size)
self.decode_extension_word(system, None)?
},
0b100 => {
let data = match size {

View File

@ -18,9 +18,9 @@ use super::decode::{
sign_extend_to_long
};
use super::state::{MC68010, Status, Flags, InterruptPriority};
use super::state::{M68k, Status, Flags, InterruptPriority};
impl Steppable for MC68010 {
impl Steppable for M68k {
fn step(&mut self, system: &System) -> Result<Clock, Error> {
self.step_internal(system)?;
Ok(1)
@ -31,7 +31,7 @@ impl Steppable for MC68010 {
}
}
impl Interruptable for MC68010 {
impl Interruptable for M68k {
fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
let ipl = if state {
InterruptPriority::from_u8(priority)
@ -49,7 +49,7 @@ impl Interruptable for MC68010 {
}
}
impl MC68010 {
impl M68k {
pub fn is_running(&self) -> bool {
self.state.status != Status::Stopped
}
@ -74,9 +74,9 @@ impl MC68010 {
self.execute_current(system)?;
self.timer.cycle.end(timer);
//if (self.timer.cycle.events % 500) == 0 {
// println!("{}", self.timer);
//}
if (self.timer.cycle.events % 500) == 0 {
println!("{}", self.timer);
}
self.check_pending_interrupts(system)?;
@ -90,7 +90,7 @@ impl MC68010 {
let pending_ipl = self.state.pending_ipl as u8;
if self.state.pending_ipl != InterruptPriority::NoInterrupt {
let priority_mask = ((self.state.sr & 0x700) >> 8) as u8;
let priority_mask = ((self.state.sr & Flags::IntMask as u16) >> 8) as u8;
if (pending_ipl >= priority_mask || pending_ipl == 7) && pending_ipl >= current_ipl {
self.state.current_ipl = self.state.pending_ipl;
@ -122,7 +122,7 @@ impl MC68010 {
self.check_breakpoints();
let timer = self.timer.decode.start();
self.decoder = M68kDecoder::decode_at(system, self.state.pc)?;
self.decoder.decode_at(system, self.state.pc)?;
self.timer.decode.end(timer);
if self.debugger.use_tracing {

View File

@ -5,5 +5,5 @@ pub mod execute;
pub mod debugger;
pub mod tests;
pub use self::state::MC68010;
pub use self::state::{M68k, M68kType};

View File

@ -6,6 +6,15 @@ use crate::timers::CpuTimer;
use super::decode::M68kDecoder;
use super::debugger::M68kDebugger;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum M68kType {
MC68000,
MC68010,
MC68020,
MC68030,
}
const FLAGS_ON_RESET: u16 = 0x2700;
#[repr(u16)]
@ -16,6 +25,8 @@ pub enum Flags {
Zero = 0x0004,
Negative = 0x0008,
Extend = 0x0010,
IntMask = 0x0700,
Interrupt = 0x1000,
Supervisor = 0x2000,
Tracing = 0x8000,
}
@ -61,7 +72,7 @@ impl InterruptPriority {
}
}
pub struct MC68010State {
pub struct M68kState {
pub status: Status,
pub current_ipl: InterruptPriority,
pub pending_ipl: InterruptPriority,
@ -77,9 +88,9 @@ pub struct MC68010State {
pub vbr: u32,
}
impl MC68010State {
pub fn new() -> MC68010State {
MC68010State {
impl M68kState {
pub fn new() -> M68kState {
M68kState {
status: Status::Init,
current_ipl: InterruptPriority::NoInterrupt,
pending_ipl: InterruptPriority::NoInterrupt,
@ -97,26 +108,28 @@ impl MC68010State {
}
}
pub struct MC68010 {
pub state: MC68010State,
pub struct M68k {
pub cputype: M68kType,
pub state: M68kState,
pub decoder: M68kDecoder,
pub debugger: M68kDebugger,
pub timer: CpuTimer,
}
impl MC68010 {
pub fn new() -> MC68010 {
MC68010 {
state: MC68010State::new(),
decoder: M68kDecoder::new(0, 0),
impl M68k {
pub fn new(cputype: M68kType) -> M68k {
M68k {
cputype,
state: M68kState::new(),
decoder: M68kDecoder::new(cputype, 0, 0),
debugger: M68kDebugger::new(),
timer: CpuTimer::new(),
}
}
pub fn reset(&mut self) {
self.state = MC68010State::new();
self.decoder = M68kDecoder::new(0, 0);
self.state = M68kState::new();
self.decoder = M68kDecoder::new(self.cputype, 0, 0);
self.debugger = M68kDebugger::new();
}

View File

@ -3,13 +3,13 @@ use crate::system::System;
use crate::devices::{Steppable, wrap_addressable};
use crate::memory::{Address, Addressable, MemoryBlock};
use super::state::MC68010;
use super::decode::Instruction;
use super::state::{M68k, M68kType};
const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010;
fn init_test() -> (MC68010, System) {
fn init_test() -> (M68k, System) {
let mut system = System::new();
// Insert basic initialization
@ -19,7 +19,7 @@ fn init_test() -> (MC68010, System) {
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
let mut cpu = MC68010::new();
let mut cpu = M68k::new(M68kType::MC68010);
cpu.step(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);

View File

@ -11,8 +11,8 @@ mod system;
use crate::system::System;
use crate::memory::MemoryBlock;
use crate::cpus::m68k::MC68010;
use crate::peripherals::ata::AtaDevice;
use crate::cpus::m68k::{M68k, M68kType};
use crate::peripherals::mc68681::MC68681;
use crate::devices::{wrap_addressable, wrap_interruptable};
@ -39,7 +39,7 @@ fn main() {
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
let mut cpu = MC68010::new();
let mut cpu = M68k::new(M68kType::MC68010);
//cpu.enable_tracing();
//cpu.add_breakpoint(0x10781a);
@ -87,26 +87,11 @@ pub fn launch_slip_connection(name: String) {
use nix::unistd::sleep;
use std::process::Command;
//Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
Command::new("sudo").args(["slattach", "-s", "38400", "-p", "slip", &name]).spawn().unwrap();
Command::new("sudo").args(["ifconfig", "sl0", "192.168.1.2", "pointopoint", "192.168.1.200", "up"]).status().unwrap();
Command::new("sudo").args(["arp", "-Ds", "192.168.1.200", "enp4s0", "pub"]).status().unwrap();
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-i", "sl0", "-j", "ACCEPT"]).status().unwrap();
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-o", "sl0", "-j", "ACCEPT"]).status().unwrap();
Command::new("sudo").args(["sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_forward"]).status().unwrap();
/*
*/
/*
sudo slattach -s 38400 -p slip /dev/ttyUSB1
sudo ifconfig sl0 192.168.1.2 pointopoint 192.168.1.200 up
// (this is automatically added on my machine) >> sudo route add -host 192.168.1.200 sl0
sudo arp -Ds 192.168.1.200 enp3s0 pub
sudo iptables -A FORWARD -i sl0 -j ACCEPT
sudo iptables -A FORWARD -o sl0 -j ACCEPT
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
*/
sleep(1);
}

View File

@ -1,10 +1,22 @@
* make functions to print assembly out
* how can you add 68030 support? Should it be all one module that checks maybe during decode if the instruction is supported? Should it 'inherit' from the MC68010 object
* make tests for each instruction
* unimplemented: ADDX, BKPT, CHK, EXG, ILLEGAL, MOVEfromCCR, MOVEP, RTR, RTD, SUBX
* undecoded: ADDX, SUBX, ABCD, SBCD
* modify execution for >=MC68020: DIVSL, DIVUL, EXTB, LINK, MOVEM, MULSL, MULUL, RTM, TRAPcc, UNPK
* implement the full extension word for MC68020+
* >=MC68020 instructions: BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, CALLM, CAS, CAS2, CHK2, CMP2, PACK
* Coprocessor instructions: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc
* should you simulate clock ticks, and only step devices when they next request it
* how can you have multple CPUs
* should you simulate bus arbitration?
* check all instructions in the docs
* make tests for each instruction