use crate::core::cpu::CpuCore;
use crate::core::ea::{AddressingMode, EaResult};
use crate::core::memory::AddressBus;
use crate::core::types::Size;
impl CpuCore {
#[inline]
pub fn exec_move<B: AddressBus>(
&mut self,
bus: &mut B,
size: Size,
src_mode: AddressingMode,
dst_mode: AddressingMode,
) -> i32 {
let value = self.read_ea(bus, src_mode, size);
self.write_ea(bus, dst_mode, size, value);
self.set_logic_flags(value, size);
4
}
pub fn exec_movea<B: AddressBus>(
&mut self,
bus: &mut B,
size: Size,
src_mode: AddressingMode,
dst_reg: usize,
) -> i32 {
let value = self.read_ea(bus, src_mode, size);
let value = if size == Size::Word {
value as i16 as i32 as u32
} else {
value
};
self.set_a(dst_reg, value);
4
}
pub fn exec_lea<B: AddressBus>(
&mut self,
bus: &mut B,
src_mode: AddressingMode,
dst_reg: usize,
) -> i32 {
let ea = self.get_ea_address(bus, src_mode, Size::Long);
self.set_a(dst_reg, ea);
4
}
pub fn exec_pea<B: AddressBus>(&mut self, bus: &mut B, src_mode: AddressingMode) -> i32 {
let ea = self.get_ea_address(bus, src_mode, Size::Long);
self.push_32(bus, ea);
12
}
pub fn exec_exg(&mut self, opcode: u16) -> i32 {
let rx = ((opcode >> 9) & 7) as usize;
let ry = (opcode & 7) as usize;
let mode = (opcode >> 3) & 0x1F;
match mode {
0x08 => {
let tmp = self.d(rx);
self.set_d(rx, self.d(ry));
self.set_d(ry, tmp);
}
0x09 => {
let tmp = self.a(rx);
self.set_a(rx, self.a(ry));
self.set_a(ry, tmp);
}
0x11 => {
let tmp = self.d(rx);
self.set_d(rx, self.a(ry));
self.set_a(ry, tmp);
}
_ => {}
}
6
}
pub fn exec_link<B: AddressBus>(&mut self, bus: &mut B, reg: usize) -> i32 {
let an = self.a(reg);
self.push_32(bus, an);
self.set_a(reg, self.dar[15]);
let disp = self.read_imm_16(bus) as i16 as i32;
self.dar[15] = (self.dar[15] as i32).wrapping_add(disp) as u32;
16
}
pub fn exec_link_long<B: AddressBus>(&mut self, bus: &mut B, reg: usize) -> i32 {
let an = self.a(reg);
self.push_32(bus, an);
self.set_a(reg, self.dar[15]);
let disp = self.read_imm_32(bus) as i32;
self.dar[15] = (self.dar[15] as i32).wrapping_add(disp) as u32;
16
}
pub fn exec_unlk<B: AddressBus>(&mut self, bus: &mut B, reg: usize) -> i32 {
self.dar[15] = self.a(reg);
let value = self.pull_32(bus);
self.set_a(reg, value);
12
}
pub fn exec_movem_to_mem<B: AddressBus>(
&mut self,
bus: &mut B,
size: Size,
mode: AddressingMode,
mask: u16,
) -> i32 {
let mut count = 0;
let is_predec = matches!(mode, AddressingMode::PreDecrement(_));
let mut addr = match &mode {
AddressingMode::PreDecrement(reg) => self.a(*reg as usize),
_ => self.get_ea_address(bus, mode, size),
};
if is_predec {
for i in 0..16 {
if mask & (1 << i) != 0 {
let reg_idx = 15 - i; let value = self.dar[reg_idx];
addr = addr.wrapping_sub(size.bytes());
match size {
Size::Word => self.write_16(bus, addr, value as u16),
Size::Long => self.write_32(bus, addr, value),
_ => {}
}
count += 1;
}
}
if let AddressingMode::PreDecrement(reg) = mode {
self.set_a(reg as usize, addr);
}
} else {
for i in 0..16 {
if mask & (1 << i) != 0 {
let value = self.dar[i];
match size {
Size::Word => self.write_16(bus, addr, value as u16),
Size::Long => self.write_32(bus, addr, value),
_ => {}
}
addr = addr.wrapping_add(size.bytes());
count += 1;
}
}
}
8 + count * if size == Size::Long { 8 } else { 4 }
}
pub fn exec_movem_to_reg<B: AddressBus>(
&mut self,
bus: &mut B,
size: Size,
mode: AddressingMode,
mask: u16,
) -> i32 {
let mut count = 0;
let is_predec = matches!(mode, AddressingMode::PreDecrement(_));
let mut addr = match &mode {
AddressingMode::PostIncrement(reg) => self.a(*reg as usize),
AddressingMode::PreDecrement(reg) => self.a(*reg as usize),
_ => self.get_ea_address(bus, mode, size),
};
if is_predec {
for i in 0..16 {
if mask & (1 << i) != 0 {
let reg_idx = 15 - i;
addr = addr.wrapping_sub(size.bytes());
let value = match size {
Size::Word => self.read_16(bus, addr) as i16 as i32 as u32,
Size::Long => self.read_32(bus, addr),
_ => 0,
};
self.dar[reg_idx] = value;
count += 1;
}
}
if let AddressingMode::PreDecrement(reg) = mode {
self.set_a(reg as usize, addr);
}
} else {
for i in 0..16 {
if mask & (1 << i) != 0 {
let value = match size {
Size::Word => self.read_16(bus, addr) as i16 as i32 as u32,
Size::Long => self.read_32(bus, addr),
_ => 0,
};
self.dar[i] = value;
addr = addr.wrapping_add(size.bytes());
count += 1;
}
}
if let AddressingMode::PostIncrement(reg) = mode {
self.set_a(reg as usize, addr);
}
}
12 + count * if size == Size::Long { 8 } else { 4 }
}
pub fn exec_swap(&mut self, reg: usize) -> i32 {
let value = self.d(reg);
let result = value.rotate_right(16);
self.set_d(reg, result);
self.set_logic_flags(result, Size::Long);
4
}
#[inline]
pub fn read_ea<B: AddressBus>(&mut self, bus: &mut B, mode: AddressingMode, size: Size) -> u32 {
match self.resolve_ea(bus, mode, size) {
EaResult::DataReg(reg) => self.d(reg as usize) & size.mask(),
EaResult::AddrReg(reg) => self.a(reg as usize) & size.mask(),
EaResult::Memory(addr) => match size {
Size::Byte => self.read_8(bus, addr) as u32,
Size::Word => self.read_16(bus, addr) as u32,
Size::Long => self.read_32(bus, addr),
},
EaResult::Immediate(addr) => match size {
Size::Byte => (self.read_16(bus, addr) & 0xFF) as u32,
Size::Word => self.read_16(bus, addr) as u32,
Size::Long => self.read_32(bus, addr),
},
}
}
#[inline]
pub fn write_ea<B: AddressBus>(
&mut self,
bus: &mut B,
mode: AddressingMode,
size: Size,
value: u32,
) {
match self.resolve_ea(bus, mode, size) {
EaResult::DataReg(reg) => {
let reg = reg as usize;
match size {
Size::Byte => {
self.dar[reg] = (self.dar[reg] & 0xFFFFFF00) | (value & 0xFF);
}
Size::Word => {
self.dar[reg] = (self.dar[reg] & 0xFFFF0000) | (value & 0xFFFF);
}
Size::Long => {
self.dar[reg] = value;
}
}
}
EaResult::AddrReg(reg) => {
self.dar[8 + reg as usize] = value;
}
EaResult::Memory(addr) => match size {
Size::Byte => self.write_8(bus, addr, value as u8),
Size::Word => self.write_16(bus, addr, value as u16),
Size::Long => self.write_32(bus, addr, value),
},
EaResult::Immediate(_) => {
}
}
}
pub fn read_resolved_ea<B: AddressBus>(
&mut self,
bus: &mut B,
ea: EaResult,
size: Size,
) -> u32 {
match ea {
EaResult::DataReg(reg) => self.d(reg as usize) & size.mask(),
EaResult::AddrReg(reg) => self.a(reg as usize) & size.mask(),
EaResult::Memory(addr) => match size {
Size::Byte => self.read_8(bus, addr) as u32,
Size::Word => self.read_16(bus, addr) as u32,
Size::Long => self.read_32(bus, addr),
},
EaResult::Immediate(addr) => match size {
Size::Byte => (self.read_16(bus, addr) & 0xFF) as u32,
Size::Word => self.read_16(bus, addr) as u32,
Size::Long => self.read_32(bus, addr),
},
}
}
pub fn write_resolved_ea<B: AddressBus>(
&mut self,
bus: &mut B,
ea: EaResult,
size: Size,
value: u32,
) {
match ea {
EaResult::DataReg(reg) => {
let reg = reg as usize;
match size {
Size::Byte => self.dar[reg] = (self.dar[reg] & 0xFFFFFF00) | (value & 0xFF),
Size::Word => self.dar[reg] = (self.dar[reg] & 0xFFFF0000) | (value & 0xFFFF),
Size::Long => self.dar[reg] = value,
}
}
EaResult::AddrReg(reg) => self.dar[8 + reg as usize] = value,
EaResult::Memory(addr) => match size {
Size::Byte => self.write_8(bus, addr, value as u8),
Size::Word => self.write_16(bus, addr, value as u16),
Size::Long => self.write_32(bus, addr, value),
},
EaResult::Immediate(_) => {
}
}
}
pub fn get_ea_address<B: AddressBus>(
&mut self,
bus: &mut B,
mode: AddressingMode,
size: Size,
) -> u32 {
match self.resolve_ea(bus, mode, size) {
EaResult::Memory(addr) | EaResult::Immediate(addr) => addr,
EaResult::DataReg(_) | EaResult::AddrReg(_) => 0, }
}
pub fn set_logic_flags(&mut self, value: u32, size: Size) {
let msb = size.msb_mask();
self.n_flag = if value & msb != 0 { 0x80 } else { 0 };
self.not_z_flag = value & size.mask();
self.v_flag = 0;
self.c_flag = 0;
}
}