Fixed various m68k bugs

Added support for RTR and RESET.
Fixed flags behavior for ASd
Added function to set PC, and fixed some instruction's handling of
an address fault a bit better
This commit is contained in:
transistor 2022-09-11 21:27:29 -07:00
parent d9a1295dda
commit 1a098bde6f
1 changed files with 42 additions and 27 deletions

View File

@ -162,8 +162,8 @@ impl M68k {
}
let vector = self.state.vbr + offset as u32;
self.state.pc = self.port.read_beu32(vector as Address)?;
let result = self.start_request(vector, Size::Word, MemAccess::Read, MemType::Program);
let addr = self.port.read_beu32(vector as Address)?;
let result = self.set_pc(addr);
// If BusError or AddressError, and another AddressError occurs, then halt
if number == 2 || number == 3 {
@ -258,10 +258,16 @@ impl M68k {
},
Instruction::ASd(count, target, size, shift_dir) => {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut overflow = false;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
let original = pair.0;
let mut previous_msb = get_msb(pair.0, size);
for _ in 0..count {
pair = shift_operation(pair.0, size, shift_dir, true);
if get_msb(pair.0, size) != previous_msb {
overflow = true;
}
previous_msb = get_msb(pair.0, size);
}
self.set_target_value(target, pair.0, size, Used::Twice)?;
@ -272,27 +278,22 @@ impl M68k {
self.set_flag(Flags::Carry, true);
self.set_flag(Flags::Extend, true);
}
if get_msb(pair.0, size) != get_msb(original, size) {
self.set_flag(Flags::Overflow, true);
}
self.set_flag(Flags::Overflow, overflow);
},
Instruction::Bcc(cond, offset) => {
let should_branch = self.get_current_condition(cond);
if should_branch {
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
self.set_pc((self.decoder.start + 2).wrapping_add(offset as u32))?;
}
},
Instruction::BRA(offset) => {
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
self.set_pc((self.decoder.start + 2).wrapping_add(offset as u32))?;
},
Instruction::BSR(offset) => {
self.push_long(self.state.pc)?;
let sp = *self.get_stack_pointer_mut();
self.debugger.stack_tracer.push_return(sp);
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
self.set_pc((self.decoder.start + 2).wrapping_add(offset as u32))?;
},
Instruction::BCHG(bitnum, target, size) => {
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
@ -397,7 +398,7 @@ impl M68k {
let value = sign_extend_to_long(self.get_target_value(src, size, Used::Once)?, size) as u32;
let existing = *self.get_a_reg_mut(reg);
let (result, carry) = overflowing_sub_sized(existing, value, Size::Long);
let overflow = get_sub_overflow(existing, value, result, size);
let overflow = get_sub_overflow(existing, value, result, Size::Long);
self.set_compare_flags(result, Size::Long, carry, overflow);
},
Instruction::DBcc(cond, reg, offset) => {
@ -406,7 +407,7 @@ impl M68k {
let next = ((get_value_sized(self.state.d_reg[reg as usize], Size::Word) as u16) as i16).wrapping_sub(1);
set_value_sized(&mut self.state.d_reg[reg as usize], next as u32, Size::Word);
if next != -1 {
self.state.pc = (self.decoder.start + 2).wrapping_add(offset as u32);
self.set_pc((self.decoder.start + 2).wrapping_add(offset as u32))?;
}
}
},
@ -491,16 +492,17 @@ impl M68k {
set_value_sized(&mut self.state.d_reg[reg as usize], result, to_size);
self.set_logic_flags(result, to_size);
},
//Instruction::ILLEGAL => {
//},
Instruction::ILLEGAL => {
self.exception(Exceptions::IllegalInstruction as u8, false)?;
},
Instruction::JMP(target) => {
self.state.pc = self.get_target_address(target)?;
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
let addr = self.get_target_address(target)?;
self.set_pc(addr)?;
},
Instruction::JSR(target) => {
let previous_pc = self.state.pc;
self.state.pc = self.get_target_address(target)?;
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
let addr = self.get_target_address(target)?;
self.set_pc(addr)?;
// If the address is good, then push the old PC onto the stack
self.push_long(previous_pc)?;
@ -676,9 +678,10 @@ impl M68k {
let value = self.get_target_address(target)?;
self.push_long(value)?;
},
//Instruction::RESET => {
// self.require_supervisor()?;
//},
Instruction::RESET => {
self.require_supervisor()?;
// TODO this only resets external devices and not internal ones
},
Instruction::ROd(count, target, size, shift_dir) => {
let count = self.get_target_value(count, size, Used::Once)? % 64;
let mut pair = (self.get_target_value(target, size, Used::Twice)?, false);
@ -712,16 +715,22 @@ impl M68k {
self.require_supervisor()?;
let sr = self.pop_word()?;
self.set_sr(sr);
self.state.pc = self.pop_long()?;
let addr = self.pop_long()?;
self.set_pc(addr)?;
if self.cputype >= M68kType::MC68010 {
let _ = self.pop_word()?;
}
},
//Instruction::RTR => {
//},
Instruction::RTR => {
let ccr = self.pop_word()?;
self.set_sr((self.state.sr & 0xFF00) | (ccr & 0x00FF));
let addr = self.pop_long()?;
self.set_pc(addr)?;
},
Instruction::RTS => {
self.debugger.stack_tracer.pop_return();
self.state.pc = self.pop_long()?;
let addr = self.pop_long()?;
self.set_pc(addr)?;
},
//Instruction::RTD(i16) => {
//},
@ -1146,6 +1155,12 @@ impl M68k {
Ok(value)
}
fn set_pc(&mut self, value: u32) -> Result<(), Error> {
self.state.pc = value;
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
Ok(())
}
pub fn get_bit_field_args(&self, offset: RegOrImmediate, width: RegOrImmediate) -> (u32, u32) {
let offset = self.get_reg_or_immediate(offset);
let mut width = self.get_reg_or_immediate(width) % 32;