mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-18 14:05:57 +00:00
Fixed ADDX/SUBX instructions
This commit is contained in:
parent
c4a99245e3
commit
d9a1295dda
@ -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))?;
|
||||||
|
@ -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 => {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user