use hephasm::{assemble_source, assemble_program_extended, AssemblerError};
#[test]
fn test_extended_instructions_without_flag() {
let result = assemble_source("MNO 100");
assert!(result.is_err());
if let Err(AssemblerError::ExtendedInstructionNotEnabled { instruction, line }) = result {
assert_eq!(instruction, "MNO");
assert_eq!(line, 1);
} else {
panic!("Expected ExtendedInstructionNotEnabled error");
}
}
#[test]
fn test_extended_instructions_with_flag() {
let machine_code = assemble_program_extended("MNO 100").unwrap();
assert_eq!(machine_code.len(), 1);
let expected = (0b10001u16 << 11) | (0b000u16 << 8) | 100;
assert_eq!(machine_code[0], expected);
}
#[test]
fn test_all_extended_opcodes() {
let machine_code = assemble_program_extended(r#"
MNO 10
DZI 20
MOD 30
STP
"#).unwrap();
assert_eq!(machine_code.len(), 4);
let mno_opcode = (machine_code[0] >> 11) & 0b11111;
let dzi_opcode = (machine_code[1] >> 11) & 0b11111;
let mod_opcode = (machine_code[2] >> 11) & 0b11111;
let stp_opcode = (machine_code[3] >> 11) & 0b11111;
assert_eq!(mno_opcode, 0b10001); assert_eq!(dzi_opcode, 0b10010); assert_eq!(mod_opcode, 0b10011); assert_eq!(stp_opcode, 0b00111); }
#[test]
fn test_extended_instructions_immediate_addressing() {
let machine_code = assemble_program_extended(r#"
MNO #42
DZI #7
MOD #5
"#).unwrap();
assert_eq!(machine_code.len(), 3);
for (i, expected_arg) in [42, 7, 5].iter().enumerate() {
let instruction = machine_code[i];
let addressing_mode = (instruction >> 8) & 0b111;
let argument = instruction & 0xFF;
assert_eq!(addressing_mode, 0b001); assert_eq!(argument, *expected_arg);
}
}
#[test]
fn test_extended_instructions_all_addressing_modes() {
let machine_code = assemble_program_extended(r#"
; Data section
value: RST 42
ptr: RST 200
; Instructions with different addressing modes
MNO value ; direct
DZI #10 ; immediate
MOD [ptr] ; indirect
STP
"#).unwrap();
assert!(machine_code.len() >= 5);
let mno_mode = (machine_code[2] >> 8) & 0b111; let dzi_mode = (machine_code[3] >> 8) & 0b111; let mod_mode = (machine_code[4] >> 8) & 0b111;
assert_eq!(mno_mode, 0b000); assert_eq!(dzi_mode, 0b001); assert_eq!(mod_mode, 0b010); }
#[test]
fn test_mixed_standard_and_extended_instructions() {
let machine_code = assemble_program_extended(r#"
DOD 100 ; standard instruction
MNO #5 ; extended instruction
ODE 200 ; standard instruction
DZI #2 ; extended instruction
STP ; standard instruction
"#).unwrap();
assert_eq!(machine_code.len(), 5);
let opcodes: Vec<u16> = machine_code.iter()
.map(|&instruction| (instruction >> 11) & 0b11111)
.collect();
assert_eq!(opcodes, vec![0b00001, 0b10001, 0b00010, 0b10010, 0b00111]);
}
#[test]
fn test_extended_instruction_error_messages() {
let result = assemble_source("DZI 10");
assert!(result.is_err());
if let Err(AssemblerError::ExtendedInstructionNotEnabled { instruction, .. }) = result {
assert_eq!(instruction, "DZI");
}
let result = assemble_source("MOD 10");
assert!(result.is_err());
if let Err(AssemblerError::ExtendedInstructionNotEnabled { instruction, .. }) = result {
assert_eq!(instruction, "MOD");
}
}