mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-28 08:54:40 +00:00
Reorganized decode and add some support for other m68k processors
This commit is contained in:
parent
b588563acc
commit
94141e112e
@ -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;
|
||||
}
|
||||
|
@ -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 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 & 0b100000000000) == 0b000000000000 {
|
||||
}
|
||||
} 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,28 +390,41 @@ 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 {
|
||||
} else if ins_0f00 == 0xA00 {
|
||||
if (ins & 0x0FF) == 0xFC {
|
||||
Ok(Instruction::ILLEGAL)
|
||||
} else {
|
||||
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 {
|
||||
}
|
||||
} 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 & 0b111111110000) == 0b111001000000 {
|
||||
} else if ins_00f0 == 0x40 {
|
||||
Ok(Instruction::TRAP((ins & 0x000F) as u8))
|
||||
} else if (ins & 0b111111110000) == 0b111001010000 {
|
||||
} else if ins_00f0 == 0x50 {
|
||||
let reg = get_low_reg(ins);
|
||||
if (ins & 0b1000) == 0 {
|
||||
let data = self.read_instruction_word(system)?;
|
||||
@ -390,24 +432,27 @@ impl M68kDecoder {
|
||||
} else {
|
||||
Ok(Instruction::UNLK(reg))
|
||||
}
|
||||
} else if (ins & 0b111111110000) == 0b111001100000 {
|
||||
} 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 & 0x0FFF {
|
||||
0xAFC => Ok(Instruction::ILLEGAL),
|
||||
0xE70 => Ok(Instruction::RESET),
|
||||
0xE71 => Ok(Instruction::NOP),
|
||||
0xE72 => {
|
||||
match ins & 0x00FF {
|
||||
0x70 => Ok(Instruction::RESET),
|
||||
0x71 => Ok(Instruction::NOP),
|
||||
0x72 => {
|
||||
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 => {
|
||||
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 {
|
||||
@ -423,6 +468,9 @@ impl M68kDecoder {
|
||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION));
|
||||
}
|
||||
},
|
||||
OPCG_ADDQ_SUBQ => {
|
||||
match get_size(ins) {
|
||||
@ -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,18 +543,22 @@ 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) => {
|
||||
if (ins & 0b100110000) == 0b100000000 {
|
||||
// TODO implement SUBX
|
||||
panic!("Not Implemented");
|
||||
} else {
|
||||
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 => {
|
||||
let size = if dir == 0 { Size::Word } else { Size::Long };
|
||||
@ -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)
|
||||
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,18 +620,22 @@ 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) => {
|
||||
if (ins & 0b100110000) == 0b100000000 {
|
||||
// TODO implement ADDX
|
||||
panic!("Not Implemented");
|
||||
} else {
|
||||
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 => {
|
||||
let size = if dir == 0 { Size::Word } else { Size::Long };
|
||||
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -5,5 +5,5 @@ pub mod execute;
|
||||
pub mod debugger;
|
||||
pub mod tests;
|
||||
|
||||
pub use self::state::MC68010;
|
||||
pub use self::state::{M68k, M68kType};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
19
src/main.rs
19
src/main.rs
@ -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);
|
||||
}
|
||||
|
||||
|
14
todo.txt
14
todo.txt
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user