common: add tests and opcode method

This commit is contained in:
2025-06-15 04:36:06 +01:00
parent 3c493d93fa
commit e55a1fced5
4 changed files with 271 additions and 41 deletions
+175
View File
@@ -0,0 +1,175 @@
use crate::common::instructions::*;
#[test]
fn test_opcode_basic_instructions() {
assert_eq!(Instruction::Nop.opcode(), 0x0);
assert_eq!(Instruction::Mov(Register::Rg0, Register::Rg1).opcode(), 0x1);
assert_eq!(
Instruction::MovSigned(Register::Rg0, Register::Rg1).opcode(),
0x2
);
assert_eq!(Instruction::Halt.opcode(), 0x24);
}
#[test]
fn test_opcode_data_transfer_instructions() {
assert_eq!(
Instruction::LoadByte(Register::Rg0, 0, Register::Rg1).opcode(),
0x3
);
assert_eq!(
Instruction::LoadByteSigned(Register::Rg0, 0, Register::Rg1).opcode(),
0x4
);
assert_eq!(
Instruction::LoadHalfword(Register::Rg0, 0, Register::Rg1).opcode(),
0x5
);
assert_eq!(
Instruction::LoadHalfwordSigned(Register::Rg0, 0, Register::Rg1).opcode(),
0x6
);
assert_eq!(
Instruction::LoadWord(Register::Rg0, 0, Register::Rg1).opcode(),
0x7
);
assert_eq!(
Instruction::StoreByte(Register::Rg0, 0, Register::Rg1).opcode(),
0x8
);
assert_eq!(
Instruction::StoreHalfword(Register::Rg0, 0, Register::Rg1).opcode(),
0x9
);
assert_eq!(
Instruction::StoreWord(Register::Rg0, 0, Register::Rg1).opcode(),
0xA
);
}
#[test]
fn test_opcode_immediate_instructions() {
assert_eq!(
Instruction::LoadLowerImmediate(Register::Rg0, 0).opcode(),
0xB
);
assert_eq!(
Instruction::LoadUpperImmediate(Register::Rg0, 0).opcode(),
0xC
);
}
#[test]
fn test_opcode_jump_instructions() {
assert_eq!(Instruction::Jump(Register::Rg0, 0).opcode(), 0xD);
assert_eq!(Instruction::JumpEq(Register::Rg0, 0).opcode(), 0xE);
assert_eq!(Instruction::JumpNeq(Register::Rg0, 0).opcode(), 0xF);
assert_eq!(Instruction::JumpGt(Register::Rg0, 0).opcode(), 0x10);
assert_eq!(Instruction::JumpGe(Register::Rg0, 0).opcode(), 0x11);
assert_eq!(Instruction::JumpLt(Register::Rg0, 0).opcode(), 0x12);
assert_eq!(Instruction::JumpLe(Register::Rg0, 0).opcode(), 0x13);
}
#[test]
fn test_opcode_arithmetic_instructions() {
assert_eq!(
Instruction::Compare(Register::Rg0, Register::Rg1).opcode(),
0x14
);
assert_eq!(Instruction::Increment(Register::Rg0).opcode(), 0x15);
assert_eq!(Instruction::Decrement(Register::Rg0).opcode(), 0x16);
assert_eq!(
Instruction::ShiftLeft(Register::Rg0, Register::Rg1, 0).opcode(),
0x17
);
assert_eq!(
Instruction::ShiftRight(Register::Rg0, Register::Rg1, 0).opcode(),
0x18
);
assert_eq!(
Instruction::Add(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x19
);
assert_eq!(
Instruction::Sub(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x1A
);
}
#[test]
fn test_opcode_logical_instructions() {
assert_eq!(
Instruction::And(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x1B
);
assert_eq!(
Instruction::Or(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x1C
);
assert_eq!(
Instruction::Not(Register::Rg0, Register::Rg1).opcode(),
0x1D
);
assert_eq!(
Instruction::Xor(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x1E
);
assert_eq!(
Instruction::Nand(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x1F
);
assert_eq!(
Instruction::Nor(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x20
);
assert_eq!(
Instruction::Xnor(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
0x21
);
}
#[test]
fn test_opcode_system_instructions() {
assert_eq!(
Instruction::Interrupt(Interrupt::Software(0)).opcode(),
0x22
);
assert_eq!(Instruction::IntReturn.opcode(), 0x23);
}
#[test]
fn test_opcode_top_bits_are_zero() {
// Test that opcodes have top 2 bits as 0 (6-bit opcodes)
let instructions = [
Instruction::Nop,
Instruction::Mov(Register::Rg0, Register::Rg1),
Instruction::Add(Register::Rg0, Register::Rg1, Register::Rg2),
Instruction::Halt,
];
for instruction in instructions {
let opcode = instruction.opcode();
assert_eq!(
opcode & 0xC0,
0,
"Top 2 bits should be 0 for opcode {opcode:#02x}"
);
}
}
#[test]
fn test_opcode_same_instruction_different_params() {
// Same instruction type with different parameters should have same opcode
assert_eq!(
Instruction::Mov(Register::Rg0, Register::Rg1).opcode(),
Instruction::Mov(Register::Acc, Register::Spr).opcode()
);
assert_eq!(
Instruction::Add(Register::Rg0, Register::Rg1, Register::Rg2).opcode(),
Instruction::Add(Register::Acc, Register::Spr, Register::Bpr).opcode()
);
assert_eq!(
Instruction::LoadWord(Register::Rg0, 100, Register::Rg1).opcode(),
Instruction::LoadWord(Register::Acc, 500, Register::Spr).opcode()
);
}