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); let dest = get_high_reg(ins);
match (ins & 0x08) == 0 { match (ins & 0x08) == 0 {
true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), 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 { } else {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?; let target = self.decode_lower_effective_address(memory, ins, Some(size))?;

View File

@ -180,7 +180,7 @@ impl M68k {
self.timing.reset(); self.timing.reset();
self.timer.decode.start(); 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.decoder.decode_at(&mut self.port, self.state.pc)?;
self.timer.decode.end(); self.timer.decode.end();
@ -230,8 +230,16 @@ impl M68k {
let (result1, carry1) = overflowing_add_sized(existing, value, size); let (result1, carry1) = overflowing_add_sized(existing, value, size);
let (result2, carry2) = overflowing_add_sized(result1, extend, size); let (result2, carry2) = overflowing_add_sized(result1, extend, size);
let overflow = get_add_overflow(existing, value, result2, 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); 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_flag(Flags::Extend, carry1 || carry2);
self.set_target_value(dest, result2, size, Used::Twice)?; self.set_target_value(dest, result2, size, Used::Twice)?;
}, },
Instruction::AND(src, dest, size) => { Instruction::AND(src, dest, size) => {
@ -460,7 +468,7 @@ impl M68k {
self.set_logic_flags(result, size); self.set_logic_flags(result, size);
}, },
Instruction::EORtoCCR(value) => { 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) => { Instruction::EORtoSR(value) => {
self.require_supervisor()?; self.require_supervisor()?;
@ -762,8 +770,16 @@ impl M68k {
let (result1, carry1) = overflowing_sub_sized(existing, value, size); let (result1, carry1) = overflowing_sub_sized(existing, value, size);
let (result2, carry2) = overflowing_sub_sized(result1, extend, size); let (result2, carry2) = overflowing_sub_sized(result1, extend, size);
let overflow = get_sub_overflow(existing, value, result2, 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); 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_flag(Flags::Extend, carry1 || carry2);
self.set_target_value(dest, result2, size, Used::Twice)?; self.set_target_value(dest, result2, size, Used::Twice)?;
}, },
Instruction::SWAP(reg) => { Instruction::SWAP(reg) => {
@ -1056,7 +1072,17 @@ impl M68k {
*reg_addr *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> { 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 { self.state.request.code = match mtype {
MemType::Program => FunctionCode::program(self.state.sr), MemType::Program => FunctionCode::program(self.state.sr),
MemType::Data => FunctionCode::data(self.state.sr), MemType::Data => FunctionCode::data(self.state.sr),
@ -1065,10 +1091,10 @@ impl M68k {
self.state.request.access = access; self.state.request.access = access;
self.state.request.address = addr; self.state.request.address = addr;
if size == Size::Byte || addr & 0x1 == 0 { if size == Size::Byte {
Ok(addr) Ok(addr)
} else { } 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) { fn overflowing_add_sized(operand1: u32, operand2: u32, size: Size) -> (u32, bool) {
match size { match size {
Size::Byte => { Size::Byte => {

View File

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