44 lines
1.6 KiB
Rust
44 lines
1.6 KiB
Rust
use prometeu_bytecode::decode_next;
|
|
use prometeu_bytecode::isa::core::{CoreOpCode, CoreOpCodeSpecExt};
|
|
|
|
fn emit(op: CoreOpCode, imm: Option<&[u8]>, out: &mut Vec<u8>) {
|
|
let code = op as u16;
|
|
out.extend_from_slice(&code.to_le_bytes());
|
|
let need = op.spec().imm_bytes as usize;
|
|
match (need, imm) {
|
|
(0, None) => {}
|
|
(n, Some(bytes)) if bytes.len() == n => out.extend_from_slice(bytes),
|
|
(n, Some(bytes)) => {
|
|
panic!("immediate size mismatch for {:?}: expected {}, got {}", op, n, bytes.len())
|
|
}
|
|
(n, None) => panic!("missing immediate for {:?}: need {} bytes", op, n),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn encode_decode_edge_immediates_roundtrip() {
|
|
let mut rom = Vec::new();
|
|
emit(CoreOpCode::PushI32, Some(&i32::MIN.to_le_bytes()), &mut rom);
|
|
emit(CoreOpCode::PushI32, Some(&i32::MAX.to_le_bytes()), &mut rom);
|
|
emit(CoreOpCode::FrameSync, None, &mut rom);
|
|
emit(CoreOpCode::Halt, None, &mut rom);
|
|
|
|
// Decode sequentially and validate structure + immediates
|
|
let mut pc = 0usize;
|
|
let mut seen = Vec::new();
|
|
while pc < rom.len() {
|
|
let instr = decode_next(pc, &rom).expect("decode ok");
|
|
seen.push(instr);
|
|
pc = instr.next_pc;
|
|
}
|
|
|
|
assert_eq!(seen.len(), 4);
|
|
assert_eq!(seen[0].opcode, CoreOpCode::PushI32);
|
|
assert_eq!(seen[0].imm_i32().unwrap(), i32::MIN);
|
|
assert_eq!(seen[1].opcode, CoreOpCode::PushI32);
|
|
assert_eq!(seen[1].imm_i32().unwrap(), i32::MAX);
|
|
assert_eq!(seen[2].opcode, CoreOpCode::FrameSync);
|
|
assert_eq!(seen[3].opcode, CoreOpCode::Halt);
|
|
assert_eq!(seen.last().unwrap().next_pc, rom.len());
|
|
}
|