mirror of
https://github.com/transistorfet/moa.git
synced 2024-06-11 14:29:30 +00:00
Fixed bug in MOVEM and added multiple breakpoints
This commit is contained in:
parent
b0f094cb59
commit
f453e6dde2
|
@ -5,6 +5,24 @@ use crate::memory::{Address, AddressSpace};
|
||||||
use super::execute::MC68010;
|
use super::execute::MC68010;
|
||||||
use super::execute::ERR_ILLEGAL_INSTRUCTION;
|
use super::execute::ERR_ILLEGAL_INSTRUCTION;
|
||||||
|
|
||||||
|
const OPCG_BIT_OPS: u8 = 0x0;
|
||||||
|
const OPCG_MOVE_BYTE: u8 = 0x1;
|
||||||
|
const OPCG_MOVE_LONG: u8 = 0x2;
|
||||||
|
const OPCG_MOVE_WORD: u8 = 0x3;
|
||||||
|
const OPCG_MISC: u8 = 0x04;
|
||||||
|
const OPCG_ADDQ_SUBQ: u8 = 0x5;
|
||||||
|
const OPCG_BRANCH: u8 = 0x6;
|
||||||
|
const OPCG_MOVEQ: u8 = 0x7;
|
||||||
|
const OPCG_DIV_OR: u8 = 0x8;
|
||||||
|
const OPCG_SUB: u8 = 0x9;
|
||||||
|
const OPCG_RESERVED1: u8 = 0xA;
|
||||||
|
const OPCG_CMP_EOR: u8 = 0xB;
|
||||||
|
const OPCG_MUL_AND: u8 = 0xC;
|
||||||
|
const OPCG_ADD: u8 = 0xD;
|
||||||
|
const OPCG_SHIFT: u8 = 0xE;
|
||||||
|
const OPCG_RESERVED2: u8 = 0xF;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Sign {
|
pub enum Sign {
|
||||||
Signed,
|
Signed,
|
||||||
|
@ -95,6 +113,7 @@ pub enum Instruction {
|
||||||
|
|
||||||
CLR(Target, Size),
|
CLR(Target, Size),
|
||||||
CMP(Target, Target, Size),
|
CMP(Target, Target, Size),
|
||||||
|
CMPA(Target, u8, Size),
|
||||||
|
|
||||||
DBcc(Condition, u16),
|
DBcc(Condition, u16),
|
||||||
DIV(Target, Target, Size, Sign),
|
DIV(Target, Target, Size, Sign),
|
||||||
|
@ -160,24 +179,6 @@ pub enum Instruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const OPCG_BIT_OPS: u8 = 0x0;
|
|
||||||
const OPCG_MOVE_BYTE: u8 = 0x1;
|
|
||||||
const OPCG_MOVE_LONG: u8 = 0x2;
|
|
||||||
const OPCG_MOVE_WORD: u8 = 0x3;
|
|
||||||
const OPCG_MISC: u8 = 0x04;
|
|
||||||
const OPCG_ADDQ_SUBQ: u8 = 0x5;
|
|
||||||
const OPCG_BRANCH: u8 = 0x6;
|
|
||||||
const OPCG_MOVEQ: u8 = 0x7;
|
|
||||||
const OPCG_DIV_OR: u8 = 0x8;
|
|
||||||
const OPCG_SUB: u8 = 0x9;
|
|
||||||
const OPCG_RESERVED1: u8 = 0xA;
|
|
||||||
const OPCG_CMP_EOR: u8 = 0xB;
|
|
||||||
const OPCG_MUL_AND: u8 = 0xC;
|
|
||||||
const OPCG_ADD: u8 = 0xD;
|
|
||||||
const OPCG_SHIFT: u8 = 0xE;
|
|
||||||
const OPCG_RESERVED2: u8 = 0xF;
|
|
||||||
|
|
||||||
|
|
||||||
impl MC68010 {
|
impl MC68010 {
|
||||||
fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result<u16, Error> {
|
fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result<u16, Error> {
|
||||||
let word = space.read_beu16(self.pc as Address)?;
|
let word = space.read_beu16(self.pc as Address)?;
|
||||||
|
@ -332,7 +333,7 @@ impl MC68010 {
|
||||||
} else {
|
} else {
|
||||||
let target = self.decode_lower_effective_address(space, ins, None)?;
|
let target = self.decode_lower_effective_address(space, ins, None)?;
|
||||||
let data = self.read_instruction_word(space)?;
|
let data = self.read_instruction_word(space)?;
|
||||||
let dir = if (ins & 0x0200) == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget };
|
||||||
Ok(Instruction::MOVEM(target, size, dir, data))
|
Ok(Instruction::MOVEM(target, size, dir, data))
|
||||||
}
|
}
|
||||||
} else if (ins & 0b111100000000) == 0b100000000000 {
|
} else if (ins & 0b111100000000) == 0b100000000000 {
|
||||||
|
@ -496,12 +497,12 @@ impl MC68010 {
|
||||||
},
|
},
|
||||||
(0b0, Some(size)) => {
|
(0b0, Some(size)) => {
|
||||||
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
||||||
Ok(Instruction::CMP(Target::DirectDReg(reg), target, size))
|
Ok(Instruction::CMP(target, Target::DirectDReg(reg), size))
|
||||||
},
|
},
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
let size = if optype == 0 { Size::Word } else { Size::Long };
|
let size = if optype == 0 { Size::Word } else { Size::Long };
|
||||||
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
let target = self.decode_lower_effective_address(space, ins, Some(size))?;
|
||||||
Ok(Instruction::CMP(target, Target::DirectAReg(reg), size))
|
Ok(Instruction::CMPA(target, reg, size))
|
||||||
},
|
},
|
||||||
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
|
||||||
}
|
}
|
||||||
|
@ -624,7 +625,7 @@ impl MC68010 {
|
||||||
0b111 => {
|
0b111 => {
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => {
|
0b000 => {
|
||||||
let value = self.read_instruction_word(space)? as u32;
|
let value = sign_extend_to_long(self.read_instruction_word(space)? as u32, Size::Word) as u32;
|
||||||
Target::IndirectMemory(value)
|
Target::IndirectMemory(value)
|
||||||
},
|
},
|
||||||
0b001 => {
|
0b001 => {
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub struct MC68010 {
|
||||||
|
|
||||||
pub current_instruction_addr: u32,
|
pub current_instruction_addr: u32,
|
||||||
pub current_instruction: Instruction,
|
pub current_instruction: Instruction,
|
||||||
pub breakpoint: u32,
|
pub breakpoints: Vec<u32>,
|
||||||
pub use_tracing: bool,
|
pub use_tracing: bool,
|
||||||
pub use_debugger: bool,
|
pub use_debugger: bool,
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ impl MC68010 {
|
||||||
|
|
||||||
current_instruction_addr: 0,
|
current_instruction_addr: 0,
|
||||||
current_instruction: Instruction::NOP,
|
current_instruction: Instruction::NOP,
|
||||||
breakpoint: 0,
|
breakpoints: vec![],
|
||||||
use_tracing: false,
|
use_tracing: false,
|
||||||
use_debugger: false,
|
use_debugger: false,
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ impl MC68010 {
|
||||||
|
|
||||||
self.current_instruction_addr = 0;
|
self.current_instruction_addr = 0;
|
||||||
self.current_instruction = Instruction::NOP;
|
self.current_instruction = Instruction::NOP;
|
||||||
self.breakpoint = 0;
|
self.breakpoints = vec![];
|
||||||
self.use_tracing = false;
|
self.use_tracing = false;
|
||||||
self.use_debugger = false;
|
self.use_debugger = false;
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,8 @@ impl MC68010 {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_breakpoint(&mut self, addr: Address) {
|
pub fn add_breakpoint(&mut self, addr: Address) {
|
||||||
self.breakpoint = addr as u32;
|
self.breakpoints.push(addr as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
|
||||||
|
@ -162,9 +162,12 @@ impl MC68010 {
|
||||||
self.current_instruction_addr = self.pc;
|
self.current_instruction_addr = self.pc;
|
||||||
self.current_instruction = self.decode_one(space)?;
|
self.current_instruction = self.decode_one(space)?;
|
||||||
|
|
||||||
if self.breakpoint == self.current_instruction_addr {
|
for breakpoint in &self.breakpoints {
|
||||||
self.use_tracing = true;
|
if *breakpoint == self.current_instruction_addr {
|
||||||
self.use_debugger = true;
|
self.use_tracing = true;
|
||||||
|
self.use_debugger = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.use_tracing {
|
if self.use_tracing {
|
||||||
|
@ -190,6 +193,10 @@ impl MC68010 {
|
||||||
std::io::stdin().read_line(&mut buffer).unwrap();
|
std::io::stdin().read_line(&mut buffer).unwrap();
|
||||||
match buffer.as_ref() {
|
match buffer.as_ref() {
|
||||||
"dump\n" => space.dump_memory(self.msp as Address, (0x200000 - self.msp) as Address),
|
"dump\n" => space.dump_memory(self.msp as Address, (0x200000 - self.msp) as Address),
|
||||||
|
"continue\n" => {
|
||||||
|
self.use_debugger = false;
|
||||||
|
return;
|
||||||
|
},
|
||||||
_ => { return; },
|
_ => { return; },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,6 +284,11 @@ impl MC68010 {
|
||||||
let existing = self.get_target_value(space, dest, size)?;
|
let existing = self.get_target_value(space, dest, size)?;
|
||||||
let result = self.subtract_sized_with_flags(existing, value, size);
|
let result = self.subtract_sized_with_flags(existing, value, size);
|
||||||
},
|
},
|
||||||
|
Instruction::CMPA(src, reg, size) => {
|
||||||
|
let value = self.get_target_value(space, src, size)?;
|
||||||
|
let existing = sign_extend_to_long(*self.get_a_reg_mut(reg), size) as u32;
|
||||||
|
let result = self.subtract_sized_with_flags(existing, value, Size::Long);
|
||||||
|
},
|
||||||
//Instruction::DBcc(Condition, u16) => {
|
//Instruction::DBcc(Condition, u16) => {
|
||||||
//},
|
//},
|
||||||
//Instruction::DIV(Target, Target, Size, Sign) => {
|
//Instruction::DIV(Target, Target, Size, Sign) => {
|
||||||
|
@ -374,31 +386,32 @@ impl MC68010 {
|
||||||
|
|
||||||
if dir == Direction::ToTarget {
|
if dir == Direction::ToTarget {
|
||||||
let mut mask = mask;
|
let mut mask = mask;
|
||||||
for i in 0..8 {
|
for i in (0..8).rev() {
|
||||||
if (mask & 0x01) != 0 {
|
|
||||||
self.set_target_value(space, target, self.d_reg[i], size)?;
|
|
||||||
}
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
for i in 0..8 {
|
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
let value = *self.get_a_reg_mut(i);
|
let value = *self.get_a_reg_mut(i);
|
||||||
self.set_target_value(space, target, value, size)?;
|
self.set_target_value(space, target, value, size)?;
|
||||||
}
|
}
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
}
|
}
|
||||||
|
for i in (0..8).rev() {
|
||||||
|
if (mask & 0x01) != 0 {
|
||||||
|
self.set_target_value(space, target, self.d_reg[i], size)?;
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut mask = mask;
|
let mut mask = mask;
|
||||||
for i in (0..8).rev() {
|
for i in 0..8 {
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
let value = *self.get_a_reg_mut(i);
|
self.d_reg[i] = self.get_target_value(space, target, size)?;
|
||||||
self.set_target_value(space, target, value, size)?;
|
|
||||||
}
|
}
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
}
|
}
|
||||||
for i in (0..8).rev() {
|
for i in 0..8 {
|
||||||
if (mask & 0x01) != 0 {
|
if (mask & 0x01) != 0 {
|
||||||
self.set_target_value(space, target, self.d_reg[i], size)?;
|
let value = self.get_target_value(space, target, size)?;
|
||||||
|
let addr = self.get_a_reg_mut(i);
|
||||||
|
*addr = value;
|
||||||
}
|
}
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
}
|
}
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -25,7 +25,10 @@ fn main() {
|
||||||
space.insert(0x00700000, Box::new(serial));
|
space.insert(0x00700000, Box::new(serial));
|
||||||
|
|
||||||
let mut cpu = MC68010::new();
|
let mut cpu = MC68010::new();
|
||||||
cpu.set_breakpoint(0x0ea0);
|
//cpu.add_breakpoint(0x07f8);
|
||||||
|
//cpu.add_breakpoint(0x0836);
|
||||||
|
//cpu.add_breakpoint(0x0838);
|
||||||
|
|
||||||
cpu.use_tracing = true;
|
cpu.use_tracing = true;
|
||||||
while cpu.is_running() {
|
while cpu.is_running() {
|
||||||
match cpu.step(&mut space) {
|
match cpu.step(&mut space) {
|
||||||
|
@ -38,5 +41,13 @@ fn main() {
|
||||||
|
|
||||||
//serial.step();
|
//serial.step();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO I need to add a way to decode and dump the assembly for a section of code, in debugger
|
||||||
|
/*
|
||||||
|
cpu.pc = 0x07f8;
|
||||||
|
while cpu.is_running() {
|
||||||
|
cpu.decode_next(&mut space).unwrap();
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ impl Addressable for MemoryBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self, addr: Address, count: usize) -> Vec<u8> {
|
fn read(&mut self, addr: Address, count: usize) -> Vec<u8> {
|
||||||
self.contents[(addr as usize) .. (addr as usize + count)].to_vec()
|
let size = if addr as usize + count < self.contents.len() { addr as usize + count } else { self.contents.len() };
|
||||||
|
self.contents[(addr as usize) .. size].to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&mut self, mut addr: Address, data: &[u8]) {
|
fn write(&mut self, mut addr: Address, data: &[u8]) {
|
||||||
|
@ -112,7 +113,12 @@ impl AddressSpace {
|
||||||
let mut line = format!("{:#010x}: ", addr);
|
let mut line = format!("{:#010x}: ", addr);
|
||||||
let to = if count < 16 { count / 2 } else { 8 };
|
let to = if count < 16 { count / 2 } else { 8 };
|
||||||
for i in 0..to {
|
for i in 0..to {
|
||||||
line += &format!("{:#06x} ", self.read_beu16(addr).unwrap());
|
let word = self.read_beu16(addr);
|
||||||
|
if word.is_err() {
|
||||||
|
println!("{}", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
line += &format!("{:#06x} ", word.unwrap());
|
||||||
addr += 2;
|
addr += 2;
|
||||||
count -= 2;
|
count -= 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user