Fixed ADDX/SUBX instructions

This commit is contained in:
transistor 2022-09-11 20:08:29 -07:00
parent c4a99245e3
commit d9a1295dda
3 changed files with 47 additions and 13 deletions

View File

@ -435,7 +435,7 @@ impl M68kDecoder {
let dest = get_high_reg(ins);
match (ins & 0x08) == 0 {
true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)),
false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::DirectDReg(dest), size)),
false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)),
}
} else {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;

View File

@ -180,7 +180,7 @@ impl M68k {
self.timing.reset();
self.timer.decode.start();
self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?;
self.start_instruction_request(self.state.pc)?;
self.decoder.decode_at(&mut self.port, self.state.pc)?;
self.timer.decode.end();
@ -230,8 +230,16 @@ impl M68k {
let (result1, carry1) = overflowing_add_sized(existing, value, size);
let (result2, carry2) = overflowing_add_sized(result1, extend, size);
let overflow = get_add_overflow(existing, value, result2, size);
// Handle flags
let zero = self.get_flag(Flags::Zero);
self.set_compare_flags(result2, size, carry1 || carry2, overflow);
if self.get_flag(Flags::Zero) {
// ADDX can only clear the zero flag, so if it's set, restore it to whatever it was before
self.set_flag(Flags::Zero, zero);
}
self.set_flag(Flags::Extend, carry1 || carry2);
self.set_target_value(dest, result2, size, Used::Twice)?;
},
Instruction::AND(src, dest, size) => {
@ -460,7 +468,7 @@ impl M68k {
self.set_logic_flags(result, size);
},
Instruction::EORtoCCR(value) => {
self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16));
self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16)));
},
Instruction::EORtoSR(value) => {
self.require_supervisor()?;
@ -762,8 +770,16 @@ impl M68k {
let (result1, carry1) = overflowing_sub_sized(existing, value, size);
let (result2, carry2) = overflowing_sub_sized(result1, extend, size);
let overflow = get_sub_overflow(existing, value, result2, size);
// Handle flags
let zero = self.get_flag(Flags::Zero);
self.set_compare_flags(result2, size, carry1 || carry2, overflow);
if self.get_flag(Flags::Zero) {
// SUBX can only clear the zero flag, so if it's set, restore it to whatever it was before
self.set_flag(Flags::Zero, zero);
}
self.set_flag(Flags::Extend, carry1 || carry2);
self.set_target_value(dest, result2, size, Used::Twice)?;
},
Instruction::SWAP(reg) => {
@ -1056,7 +1072,17 @@ impl M68k {
*reg_addr
}
pub fn start_instruction_request(&mut self, addr: u32) -> Result<u32, Error> {
self.state.request.is_instruction = true;
self.state.request.code = FunctionCode::program(self.state.sr);
self.state.request.access = MemAccess::Read;
self.state.request.address = addr;
validate_address(addr)
}
pub fn start_request(&mut self, addr: u32, size: Size, access: MemAccess, mtype: MemType) -> Result<u32, Error> {
self.state.request.is_instruction = false;
self.state.request.code = match mtype {
MemType::Program => FunctionCode::program(self.state.sr),
MemType::Data => FunctionCode::data(self.state.sr),
@ -1065,10 +1091,10 @@ impl M68k {
self.state.request.access = access;
self.state.request.address = addr;
if size == Size::Byte || addr & 0x1 == 0 {
if size == Size::Byte {
Ok(addr)
} else {
Err(Error::processor(Exceptions::AddressError as u32))
validate_address(addr)
}
}
@ -1293,6 +1319,14 @@ impl M68k {
}
}
fn validate_address(addr: u32) -> Result<u32, Error> {
if addr & 0x1 == 0 {
Ok(addr)
} else {
Err(Error::processor(Exceptions::AddressError as u32))
}
}
fn overflowing_add_sized(operand1: u32, operand2: u32, size: Size) -> (u32, bool) {
match size {
Size::Byte => {

View File

@ -98,6 +98,7 @@ pub enum MemAccess {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct MemoryRequest {
pub is_instruction: bool,
pub access: MemAccess,
pub code: FunctionCode,
pub size: Size,
@ -180,11 +181,10 @@ impl M68k {
println!("PC: {:#010x}", self.state.pc);
println!("SR: {:#06x}", self.state.sr);
for i in 0..7 {
println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]);
println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]);
}
println!("D7: {:#010x}", self.state.d_reg[7]);
println!("SSP: {:#010x}", self.state.ssp);
println!("USP: {:#010x}", self.state.usp);
println!("D7: {:#010x} USP: {:#010x}", self.state.d_reg[7], self.state.ssp);
println!(" SSP: {:#010x}", self.state.ssp);
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
println!("");
@ -229,6 +229,7 @@ impl FunctionCode {
impl MemoryRequest {
pub fn new() -> Self {
Self {
is_instruction: false,
access: MemAccess::Read,
code: FunctionCode::Reserved0,
size: Size::Word,
@ -237,10 +238,9 @@ impl MemoryRequest {
}
pub fn get_type_code(&self) -> u16 {
let ins = match self.code {
// TODO this is wrong (should be opposite results), but is a temporary hack
FunctionCode::SupervisorProgram | FunctionCode::UserProgram => 0x0008,
_ => 0x0000,
let ins = match self.is_instruction {
true => 0x0000,
false => 0x0008,
};
let rw = match self.access {