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

View File

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

View File

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

View File

@ -5,5 +5,5 @@ pub mod execute;
pub mod debugger; pub mod debugger;
pub mod tests; 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::decode::M68kDecoder;
use super::debugger::M68kDebugger; 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; const FLAGS_ON_RESET: u16 = 0x2700;
#[repr(u16)] #[repr(u16)]
@ -16,6 +25,8 @@ pub enum Flags {
Zero = 0x0004, Zero = 0x0004,
Negative = 0x0008, Negative = 0x0008,
Extend = 0x0010, Extend = 0x0010,
IntMask = 0x0700,
Interrupt = 0x1000,
Supervisor = 0x2000, Supervisor = 0x2000,
Tracing = 0x8000, Tracing = 0x8000,
} }
@ -61,7 +72,7 @@ impl InterruptPriority {
} }
} }
pub struct MC68010State { pub struct M68kState {
pub status: Status, pub status: Status,
pub current_ipl: InterruptPriority, pub current_ipl: InterruptPriority,
pub pending_ipl: InterruptPriority, pub pending_ipl: InterruptPriority,
@ -77,9 +88,9 @@ pub struct MC68010State {
pub vbr: u32, pub vbr: u32,
} }
impl MC68010State { impl M68kState {
pub fn new() -> MC68010State { pub fn new() -> M68kState {
MC68010State { M68kState {
status: Status::Init, status: Status::Init,
current_ipl: InterruptPriority::NoInterrupt, current_ipl: InterruptPriority::NoInterrupt,
pending_ipl: InterruptPriority::NoInterrupt, pending_ipl: InterruptPriority::NoInterrupt,
@ -97,26 +108,28 @@ impl MC68010State {
} }
} }
pub struct MC68010 { pub struct M68k {
pub state: MC68010State, pub cputype: M68kType,
pub state: M68kState,
pub decoder: M68kDecoder, pub decoder: M68kDecoder,
pub debugger: M68kDebugger, pub debugger: M68kDebugger,
pub timer: CpuTimer, pub timer: CpuTimer,
} }
impl MC68010 { impl M68k {
pub fn new() -> MC68010 { pub fn new(cputype: M68kType) -> M68k {
MC68010 { M68k {
state: MC68010State::new(), cputype,
decoder: M68kDecoder::new(0, 0), state: M68kState::new(),
decoder: M68kDecoder::new(cputype, 0, 0),
debugger: M68kDebugger::new(), debugger: M68kDebugger::new(),
timer: CpuTimer::new(), timer: CpuTimer::new(),
} }
} }
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.state = MC68010State::new(); self.state = M68kState::new();
self.decoder = M68kDecoder::new(0, 0); self.decoder = M68kDecoder::new(self.cputype, 0, 0);
self.debugger = M68kDebugger::new(); self.debugger = M68kDebugger::new();
} }

View File

@ -3,13 +3,13 @@ use crate::system::System;
use crate::devices::{Steppable, wrap_addressable}; use crate::devices::{Steppable, wrap_addressable};
use crate::memory::{Address, Addressable, MemoryBlock}; use crate::memory::{Address, Addressable, MemoryBlock};
use super::state::MC68010;
use super::decode::Instruction; use super::decode::Instruction;
use super::state::{M68k, M68kType};
const INIT_STACK: Address = 0x00002000; const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010; const INIT_ADDR: Address = 0x00000010;
fn init_test() -> (MC68010, System) { fn init_test() -> (M68k, System) {
let mut system = System::new(); let mut system = System::new();
// Insert basic initialization // 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(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR 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(); cpu.step(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32); assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK 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::system::System;
use crate::memory::MemoryBlock; use crate::memory::MemoryBlock;
use crate::cpus::m68k::MC68010;
use crate::peripherals::ata::AtaDevice; use crate::peripherals::ata::AtaDevice;
use crate::cpus::m68k::{M68k, M68kType};
use crate::peripherals::mc68681::MC68681; use crate::peripherals::mc68681::MC68681;
use crate::devices::{wrap_addressable, wrap_interruptable}; use crate::devices::{wrap_addressable, wrap_interruptable};
@ -39,7 +39,7 @@ fn main() {
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap(); 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.enable_tracing();
//cpu.add_breakpoint(0x10781a); //cpu.add_breakpoint(0x10781a);
@ -87,26 +87,11 @@ pub fn launch_slip_connection(name: String) {
use nix::unistd::sleep; use nix::unistd::sleep;
use std::process::Command; 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(["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(["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(["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", "-i", "sl0", "-j", "ACCEPT"]).status().unwrap();
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-o", "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(); 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 * 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 * how can you have multple CPUs
* should you simulate bus arbitration? * should you simulate bus arbitration?
* check all instructions in the docs * check all instructions in the docs
* make tests for each instruction