Fixed instruction decode for MOVEM and EXT

It's now possible to run the monitor program until it loops waiting
for the serial transmitter to be ready for writing
This commit is contained in:
transistor 2021-09-30 15:15:23 -07:00
parent e40663ee9a
commit 7868bc3014
3 changed files with 64 additions and 37 deletions

View File

@ -285,13 +285,7 @@ impl MC68010 {
let src = self.decode_lower_effective_address(space, ins, None)?;
let dest = get_high_reg(ins);
Ok(Instruction::LEA(src, dest))
} else if (ins & 0b101110000000) == 0b100010000000 {
let target = self.decode_lower_effective_address(space, ins, None)?;
let data = self.read_instruction_word(space)?;
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
let dir = if (ins & 0x0200) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data))
} else if (ins & 0b100000000000) == 0 {
} else if (ins & 0b100000000000) == 0b000000000000 {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
match (ins & 0x0700) >> 8 {
0b000 => {
@ -320,22 +314,22 @@ impl MC68010 {
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0b111100000000) == 0b101000000000 {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Word))?;
match get_size(ins) {
Some(size) => Ok(Instruction::TST(target, size)),
None => Ok(Instruction::TAS(target)),
} 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 target = self.decode_lower_effective_address(space, ins, None)?;
let data = self.read_instruction_word(space)?;
let dir = if (ins & 0x0200) == 0 { Direction::ToTarget } else { Direction::FromTarget };
Ok(Instruction::MOVEM(target, size, dir, data))
}
} else if (ins & 0b111100000000) == 0b100000000000 {
let subselect = (ins & 0x01C0) >> 6;
let mode = get_low_mode(ins);
match (subselect, mode) {
(0b010, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Word))
},
(0b011, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Long))
},
(0b000, _) => {
let target = self.decode_lower_effective_address(space, ins, Some(Size::Byte))?;
Ok(Instruction::NBCD(target))
@ -349,6 +343,12 @@ impl MC68010 {
},
_ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)),
}
} else if (ins & 0b111100000000) == 0b101000000000 {
let target = self.decode_lower_effective_address(space, 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(space, ins, None)?;
if (ins & 0b01000000) == 0 {

View File

@ -32,6 +32,8 @@ pub struct MC68010 {
pub current_instruction_addr: u32,
pub current_instruction: Instruction,
pub breakpoint: u32,
pub use_debugger: bool,
}
const FLAGS_ON_RESET: u16 = 0x2700;
@ -62,6 +64,8 @@ impl MC68010 {
current_instruction_addr: 0,
current_instruction: Instruction::NOP,
breakpoint: 0,
use_debugger: false,
}
}
@ -78,6 +82,8 @@ impl MC68010 {
self.current_instruction_addr = 0;
self.current_instruction = Instruction::NOP;
self.breakpoint = 0;
self.use_debugger = false;
}
pub fn is_running(&self) -> bool {
@ -94,6 +100,10 @@ impl MC68010 {
Ok(())
}
pub fn set_breakpoint(&mut self, addr: Address) {
self.breakpoint = addr as u32;
}
pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> {
match self.state {
State::Init => self.init(space),
@ -146,19 +156,23 @@ impl MC68010 {
self.current_instruction_addr = self.pc;
self.current_instruction = self.decode_one(space)?;
/*
// Print instruction bytes for debugging
let ins_data: Result<String, Error> =
(0..((self.pc - current_ins_addr) / 2)).map(|offset|
Ok(format!("{:04x} ", space.read_beu16((current_ins_addr + (offset * 2)) as Address)?))
).collect();
debug!("{:#010x}: {}\n\t{:?}\n", current_ins_addr, ins_data?, ins);
if self.breakpoint == self.current_instruction_addr {
self.use_debugger = true;
}
// Single Step
self.dump_state();
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).unwrap();
*/
if self.use_debugger {
// Print instruction bytes for debugging
let ins_data: Result<String, Error> =
(0..((self.pc - self.current_instruction_addr) / 2)).map(|offset|
Ok(format!("{:04x} ", space.read_beu16((self.current_instruction_addr + (offset * 2)) as Address)?))
).collect();
debug!("{:#010x}: {}\n\t{:?}\n", self.current_instruction_addr, ins_data?, self.current_instruction);
// Single Step
self.dump_state(space);
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).unwrap();
}
Ok(())
}
@ -236,8 +250,10 @@ impl MC68010 {
//},
//Instruction::EXG(Target, Target) => {
//},
//Instruction::EXT(u8, Size) => {
//},
Instruction::EXT(reg, size) => {
let data: u8 = self.d_reg[reg as usize] as u8;
self.d_reg[reg as usize] = sign_extend_byte(data, size);
},
//Instruction::ILLEGAL => {
//},
Instruction::JMP(target) => {
@ -266,8 +282,10 @@ impl MC68010 {
Instruction::MOVEtoSR(target) => {
self.sr = self.get_target_value(space, target, Size::Word)? as u16;
},
//Instruction::MOVEtoCCR(Target) => {
//},
Instruction::MOVEtoCCR(target) => {
let value = self.get_target_value(space, target, Size::Word)? as u16;
self.sr = (self.sr & 0xFF00) | (value & 0x00FF);
},
Instruction::MOVEC(target, control_reg, dir) => {
match dir {
Direction::FromTarget => {
@ -286,7 +304,7 @@ impl MC68010 {
//},
Instruction::MOVEM(target, size, dir, mask) => {
// TODO moving words requires a sign extension to 32 bits
if size != Size::Long { panic!("Unsupported size in MOVEM instruction"); }
if size != Size::Long { return Err(Error::new("Unsupported size in MOVEM instruction")); }
if dir == Direction::ToTarget {
let mut mask = mask;
@ -321,7 +339,7 @@ impl MC68010 {
}
},
Instruction::MOVEQ(data, reg) => {
let value = ((data as i8) as i32) as u32;
let value = sign_extend_byte(data, Size::Long);
self.d_reg[reg as usize] = value;
},
//Instruction::MUL(Target, Target, Size, Sign) => {
@ -558,7 +576,7 @@ impl MC68010 {
if carry {
flags |= FLAGS_CARRY | FLAGS_OVERFLOW;
}
self.sr |= (self.sr & 0xFFF0) | flags;
self.sr = (self.sr & 0xFFF0) | flags;
}
fn set_logic_flags(&mut self, value: u32, size: Size) {
@ -635,6 +653,14 @@ fn set_address_sized(space: &mut AddressSpace, addr: Address, value: u32, size:
}
}
fn sign_extend_byte(value: u8, size: Size) -> u32 {
let value = (value as i8);
match size {
Size::Byte => (value as u8) as u32,
Size::Word => ((value as i16) as u16) as u32,
Size::Long => (value as i32) as u32,
}
}
/*
impl Processor for MC68010 {

View File

@ -24,6 +24,7 @@ fn main() {
space.insert(0x00700000, Box::new(serial));
let mut cpu = MC68010::new();
cpu.set_breakpoint(0x0838);
while cpu.is_running() {
match cpu.step(&mut space) {
Ok(()) => { },