1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// MOVE16 - 16-byte Aligned Block Transfer (68030/68040)
//
// Opcode (Ax)+,(Ay)+: 1111 0110 0010 0yyy with extension 1xxx 0000 0000 0000
// Transfers 16 bytes from source to destination, both addresses aligned to 16-byte boundary
use crate::core::cpu::CpuCore;
use crate::core::memory::AddressBus;
impl CpuCore {
/// MOVE16 - 16-byte aligned block transfer (68030/68040).
/// Format: (Ax)+,(Ay)+
/// Opcode: 1111 0110 0010 0yyy, extension: 1xxx 0000 0000 0000
pub fn exec_move16<B: AddressBus>(&mut self, bus: &mut B, opcode: u16) -> i32 {
// Read extension word to get destination register
let ext = self.read_imm_16(bus);
// Note: For MOVE16 (Ax)+,(Ay)+:
// - Opcode bits 2:0 = source register Ax
// - Extension bits 14:12 = destination register Ay
// (This matches gas assembler output)
let src_reg = (opcode & 7) as usize;
let dst_reg = ((ext >> 12) & 7) as usize;
// MOVE16 requires 16-byte alignment for both addresses.
let src_raw = self.a(src_reg);
if (src_raw & 0xF) != 0 {
self.trigger_address_error(bus, src_raw, false, false);
return 0;
}
let dst_raw = self.a(dst_reg);
if (dst_raw & 0xF) != 0 {
self.trigger_address_error(bus, dst_raw, true, false);
return 0;
}
// Get source and destination addresses (already aligned)
let src_addr = src_raw;
let dst_addr = dst_raw;
// Transfer 16 bytes (4 longwords) - use bus directly for transfers
for i in 0u32..4 {
let offset = i * 4;
let value = bus.read_long(src_addr + offset);
bus.write_long(dst_addr + offset, value);
}
// Increment both registers by 16
self.set_a(src_reg, self.a(src_reg).wrapping_add(16));
self.set_a(dst_reg, self.a(dst_reg).wrapping_add(16));
// Condition codes are not affected
4
}
}