mirror of
https://github.com/transistorfet/moa.git
synced 2025-01-08 00:29:29 +00:00
Fixed some bugs and added the ROXd instruction
This commit is contained in:
parent
3579529764
commit
e81a5d430a
@ -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)
|
||||
},
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user