mirror of
https://github.com/0xNikilite/oboromi.git
synced 2026-01-31 01:15:22 +01:00
Refactor decode_and_execute to streamline NOP and MOV handling; add real ADD instruction test
This commit is contained in:
@@ -55,35 +55,52 @@ impl CPU {
|
||||
|
||||
/// Decode and execute a single ARM64 opcode.
|
||||
pub fn decode_and_execute(&mut self, opcode: u32) {
|
||||
// 1) NOP and fake ADD cases first
|
||||
match opcode {
|
||||
0xD503201F => {
|
||||
// NOP: do nothing
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
return;
|
||||
}
|
||||
0xD2802674 => {
|
||||
// Fake ADD X0, X1, X2
|
||||
self.regs.add_with_flags(0, self.regs.x[1], self.regs.x[2]);
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
// 1) NOP
|
||||
if opcode == 0xD503201F {
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) MOV alias: ORR Xd, XZR, #imm12 (dynamic)
|
||||
const MOV_MASK: u32 = 0b1111111 << 25; // bits 31–25
|
||||
const MOV_PATTERN: u32 = 0b1010000 << 25; // pattern for ORR immediate
|
||||
// 2) MOV (ORR Xd, XZR, #imm12)
|
||||
const MOV_MASK: u32 = 0b1111111 << 25;
|
||||
const MOV_PATTERN: u32 = 0b1010000 << 25;
|
||||
if (opcode & MOV_MASK) == MOV_PATTERN {
|
||||
let rd = (opcode & 0x1F) as usize; // bits [4:0]
|
||||
let imm12 = ((opcode >> 10) & 0xFFF) as u64; // bits [21:10]
|
||||
let rd = (opcode & 0x1F) as usize;
|
||||
let imm12 = ((opcode >> 10) & 0xFFF) as u64;
|
||||
self.regs.x[rd] = imm12;
|
||||
self.regs.set_nz(imm12);
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) Unimplemented
|
||||
// 3) ADD/SUB (register-register)
|
||||
// Pattern bits [31:21] = 10001011000 (ADD), 11001011000 (SUB)
|
||||
const ARITH_MASK: u32 = 0xFFE00000; // mask bits 31..21
|
||||
const ADD_OPCODE: u32 = 0x8B000000; // ADD Xd, Xn, Xm
|
||||
const SUB_OPCODE: u32 = 0xCB000000; // SUB Xd, Xn, Xm
|
||||
if (opcode & ARITH_MASK) == ADD_OPCODE || (opcode & ARITH_MASK) == SUB_OPCODE {
|
||||
let rd = (opcode & 0x1F) as usize;
|
||||
let rn = ((opcode >> 5) & 0x1F) as usize;
|
||||
let rm = ((opcode >> 16) & 0x1F) as usize;
|
||||
|
||||
let src1 = self.regs.x[rn];
|
||||
let src2 = self.regs.x[rm];
|
||||
|
||||
let result = if (opcode & ARITH_MASK) == ADD_OPCODE {
|
||||
self.regs.set_cv_add(src1, src2);
|
||||
src1.wrapping_add(src2)
|
||||
} else {
|
||||
self.regs.set_cv_add(src1, !src2 + 1);
|
||||
src1.wrapping_sub(src2)
|
||||
};
|
||||
|
||||
self.regs.x[rd] = result;
|
||||
self.regs.set_nz(result);
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4) Fallback
|
||||
println!("⚠️ Unimplemented opcode: {:08X}", opcode);
|
||||
self.regs.pc = self.regs.pc.wrapping_add(4);
|
||||
}
|
||||
|
||||
28
src/main.rs
28
src/main.rs
@@ -1,6 +1,5 @@
|
||||
use oboromi::cpu::CPU;
|
||||
use oboromi::memory::Memory;
|
||||
use oboromi::cpu::Flags;
|
||||
|
||||
/// Simple helper to decode basic ARM64 instruction fields from a 32-bit opcode.
|
||||
/// Returns a tuple (sf, opc, rn, rd).
|
||||
@@ -35,20 +34,6 @@ fn main() {
|
||||
assert_eq!(cpu.regs.pc, 4);
|
||||
println!("✅ NOP executed correctly, PC = {}", cpu.regs.pc);
|
||||
|
||||
// 3) Test ADD with flags: fake opcode 0xD2802674 implements ADD X0, X1, X2
|
||||
cpu.regs.x[1] = 5;
|
||||
cpu.regs.x[2] = 7;
|
||||
cpu.regs.pc = 0;
|
||||
let add = 0xD2802674_u32.to_le_bytes();
|
||||
for i in 0..4 {
|
||||
cpu.memory.write_byte(i, add[i]);
|
||||
}
|
||||
cpu.step();
|
||||
// After ADD, X0 = 5 + 7 = 12, Zero flag should be false
|
||||
assert_eq!(cpu.regs.x[0], 12);
|
||||
assert!(!cpu.regs.flags.contains(Flags::ZERO));
|
||||
println!("✅ ADD executed: X0 = {}, Flags = {:?}", cpu.regs.x[0], cpu.regs.flags);
|
||||
|
||||
// 4) Test dynamic MOV Xd, #imm decoding
|
||||
// MOV X5, #0x2A => ORR X5, XZR, #0x2A
|
||||
let mut cpu2 = CPU::new(1024);
|
||||
@@ -71,4 +56,17 @@ fn main() {
|
||||
let (sf, opc, rn, rd) = decode_arm64_fields(opcode);
|
||||
println!("Decoded 0x{:08X}: sf={}, opc={}, rn={}, rd={}", opcode, sf, opc, rn, rd);
|
||||
}
|
||||
|
||||
// 5) Test istruzione reale: ADD X1, X1, X2 (opcode: 0x8B020021)
|
||||
let add_real = 0x8B020021_u32.to_le_bytes();
|
||||
for i in 0..4 {
|
||||
cpu.memory.write_byte(i, add_real[i]);
|
||||
}
|
||||
cpu.regs.x[1] = 10;
|
||||
cpu.regs.x[2] = 32;
|
||||
cpu.regs.pc = 0;
|
||||
cpu.step();
|
||||
assert_eq!(cpu.regs.x[1], 42);
|
||||
println!("✅ Real ADD executed correctly: X1 = {}", cpu.regs.x[1]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user