Fixed some bugs and added the ROXd instruction

This commit is contained in:
transistor 2021-10-19 19:50:42 -07:00
parent 3579529764
commit e81a5d430a
3 changed files with 88 additions and 14 deletions

View File

@ -347,7 +347,7 @@ impl M68k {
return Ok(());
}
let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Word);
let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Long);
let (remainder, quotient) = match sign {
Sign::Signed => {
let value = sign_extend_to_long(value, Size::Word) as u32;
@ -574,7 +574,20 @@ impl M68k {
let count = self.get_target_value(system, count, size)? % 64;
let mut pair = (self.get_target_value(system, target, size)?, false);
for _ in 0..count {
pair = rotate_operation(pair.0, size, shift_dir);
pair = rotate_operation(pair.0, size, shift_dir, None);
}
self.set_logic_flags(pair.0, size);
if pair.1 {
self.set_flag(Flags::Carry, true);
}
self.set_target_value(system, target, pair.0, size)?;
},
Instruction::ROXd(count, target, size, shift_dir) => {
let count = self.get_target_value(system, count, size)? % 64;
let mut pair = (self.get_target_value(system, target, size)?, false);
for _ in 0..count {
pair = rotate_operation(pair.0, size, shift_dir, Some(self.get_flag(Flags::Extend)));
self.set_flag(Flags::Extend, pair.1);
}
self.set_logic_flags(pair.0, size);
if pair.1 {
@ -582,8 +595,6 @@ impl M68k {
}
self.set_target_value(system, target, pair.0, size)?;
},
//Instruction::ROXd(Target, Target, Size, ShiftDirection) => {
//},
Instruction::RTE => {
self.require_supervisor()?;
self.state.sr = self.pop_word(system)?;
@ -791,11 +802,11 @@ impl M68k {
Target::IndirectARegInc(reg) => {
let addr = self.get_a_reg_mut(reg);
set_address_sized(system, *addr as Address, value, size)?;
*addr += size.in_bytes();
*addr = (*addr).wrapping_add(size.in_bytes());
},
Target::IndirectARegDec(reg) => {
let addr = self.get_a_reg_mut(reg);
*addr -= size.in_bytes();
*addr = (*addr).wrapping_sub(size.in_bytes());
set_address_sized(system, *addr as Address, value, size)?;
},
Target::IndirectRegOffset(base_reg, index_reg, displacement) => {
@ -1056,11 +1067,11 @@ fn shift_operation(value: u32, size: Size, dir: ShiftDirection, arithmetic: bool
}
}
fn rotate_operation(value: u32, size: Size, dir: ShiftDirection) -> (u32, bool) {
fn rotate_operation(value: u32, size: Size, dir: ShiftDirection, use_extend: Option<bool>) -> (u32, bool) {
match dir {
ShiftDirection::Left => {
let bit = get_msb(value, size);
let mask = if bit { 0x01 } else { 0x00 };
let mask = if use_extend.unwrap_or(bit) { 0x01 } else { 0x00 };
match size {
Size::Byte => (mask | ((value as u8) << 1) as u32, bit),
Size::Word => (mask | ((value as u16) << 1) as u32, bit),
@ -1069,7 +1080,7 @@ fn rotate_operation(value: u32, size: Size, dir: ShiftDirection) -> (u32, bool)
},
ShiftDirection::Right => {
let bit = if (value & 0x01) != 0 { true } else { false };
let mask = if bit { get_msb_mask(0xffffffff, size) } else { 0x0 };
let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 };
((value >> 1) | mask, bit)
},
}

View File

@ -370,18 +370,19 @@ mod decode_tests {
system.get_bus().write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
assert_eq!(cpu.decoder.instruction, Instruction::MULW(Target::Immediate(0x276), 0, Sign::Signed));
}
#[test]
fn instruction_mulsl() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
let (mut cpu, system) = init_decode_test(M68kType::MC68030);
system.get_bus().write_beu16(INIT_ADDR, 0x4c3c).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0800).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0000).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 6, 0x0097).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
assert_eq!(cpu.decoder.instruction, Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed));
}
#[test]
@ -552,7 +553,7 @@ mod execute_tests {
let value = 0x0276;
cpu.state.d_reg[0] = 0x0200;
cpu.decoder.instruction = Instruction::MUL(Target::Immediate(value), Target::DirectDReg(0), Size::Word, Sign::Signed);
cpu.decoder.instruction = Instruction::MULW(Target::Immediate(value), 0, Sign::Signed);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x4ec00);
@ -564,7 +565,7 @@ mod execute_tests {
let value = 0x0245;
cpu.state.d_reg[0] = 0x40000;
cpu.decoder.instruction = Instruction::DIV(Target::Immediate(value), Target::DirectDReg(0), Size::Word, Sign::Unsigned);
cpu.decoder.instruction = Instruction::DIVW(Target::Immediate(value), 0, Sign::Unsigned);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x007101C3);
@ -618,6 +619,58 @@ mod execute_tests {
assert_eq!(cpu.state.sr & 0x1F, 0x09);
}
#[test]
fn instruction_roxl() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x80;
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000000);
assert_eq!(cpu.state.sr & 0x1F, 0x15);
}
#[test]
fn instruction_roxr() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x01;
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000000);
assert_eq!(cpu.state.sr & 0x1F, 0x15);
}
#[test]
fn instruction_roxl_2() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x80;
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000001);
assert_eq!(cpu.state.sr & 0x1F, 0x00);
}
#[test]
fn instruction_roxr_2() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x01;
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000080);
assert_eq!(cpu.state.sr & 0x1F, 0x08);
}
#[test]

View File

@ -76,12 +76,21 @@ pub struct Block {
pub struct Bus {
pub blocks: Vec<Block>,
pub mask: Address,
}
impl Bus {
pub fn new() -> Bus {
Bus {
blocks: vec!(),
mask: !0,
}
}
pub fn address_limit(&mut self, bits: u8) {
self.mask = 0;
for _ in 0..bits {
self.mask = (self.mask << 1) | 0x01;
}
}
@ -97,6 +106,7 @@ impl Bus {
}
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> {
let addr = addr & self.mask;
for block in &self.blocks {
if addr >= block.base && addr <= (block.base + block.length as Address) {
let relative_addr = addr - block.base;