#![cfg(feature = "ksm")]
use kerbalobjects::ksm::sections::ArgIndex;
use kerbalobjects::ksm::{Instr, IntSize};
use kerbalobjects::{BufferIterator, Opcode};
const INSTRUCTIONS_BYTES: &[u8] = &[
0x31, 0x32, 0x33, 0x34, 0x03, 0x35, 0x36, 0x56, 0x37, 0x12, 0x38, 0x39, 0x3a, 0x13, 0x3b, 0x10, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x04, 0x06, 0x4d, 0x09, 0x4e, 0x98, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x21, 0x27, 0x54, 0x55, 0x57, 0x34, 0x58, 0x58, 0x59, 0x08, 0x5a, 0x41, 0x75, 0x5b, 0x08, 0x5c, 0x26, 0x5d, 0x12, 0x14, 0x5e, 0x10, 0x5f, 0x60, 0x61, 0x62, 0x63, 0xce, 0xa4, 0xcd, 0xc1, 0xc4, 0xf0, 0x2d, ];
const INSTRUCTIONS: &[Instr] = &[
Instr::ZeroOp(Opcode::Eof),
Instr::ZeroOp(Opcode::Eop),
Instr::ZeroOp(Opcode::Nop),
Instr::OneOp(Opcode::Sto, ArgIndex::from_usize(0x03)),
Instr::ZeroOp(Opcode::Uns),
Instr::OneOp(Opcode::Gmb, ArgIndex::from_usize(0x56)),
Instr::OneOp(Opcode::Smb, ArgIndex::from_usize(0x12)),
Instr::ZeroOp(Opcode::Gidx),
Instr::ZeroOp(Opcode::Sidx),
Instr::OneOp(Opcode::Bfa, ArgIndex::from_usize(0x13)),
Instr::OneOp(Opcode::Jmp, ArgIndex::from_usize(0x10)),
Instr::ZeroOp(Opcode::Add),
Instr::ZeroOp(Opcode::Sub),
Instr::ZeroOp(Opcode::Mul),
Instr::ZeroOp(Opcode::Div),
Instr::ZeroOp(Opcode::Pow),
Instr::ZeroOp(Opcode::Cgt),
Instr::ZeroOp(Opcode::Clt),
Instr::ZeroOp(Opcode::Cge),
Instr::ZeroOp(Opcode::Cle),
Instr::ZeroOp(Opcode::Ceq),
Instr::ZeroOp(Opcode::Cne),
Instr::ZeroOp(Opcode::Neg),
Instr::ZeroOp(Opcode::Bool),
Instr::ZeroOp(Opcode::Not),
Instr::ZeroOp(Opcode::And),
Instr::ZeroOp(Opcode::Or),
Instr::TwoOp(
Opcode::Call,
ArgIndex::from_usize(0x04),
ArgIndex::from_usize(0x06),
),
Instr::OneOp(Opcode::Ret, ArgIndex::from_usize(0x09)),
Instr::OneOp(Opcode::Push, ArgIndex::from_usize(0x98)),
Instr::ZeroOp(Opcode::Pop),
Instr::ZeroOp(Opcode::Dup),
Instr::ZeroOp(Opcode::Swap),
Instr::ZeroOp(Opcode::Eval),
Instr::TwoOp(
Opcode::Addt,
ArgIndex::from_usize(0x21),
ArgIndex::from_usize(0x27),
),
Instr::ZeroOp(Opcode::Rmvt),
Instr::ZeroOp(Opcode::Wait),
Instr::OneOp(Opcode::Gmet, ArgIndex::from_usize(0x34)),
Instr::OneOp(Opcode::Stol, ArgIndex::from_usize(0x58)),
Instr::OneOp(Opcode::Stog, ArgIndex::from_usize(0x08)),
Instr::TwoOp(
Opcode::Bscp,
ArgIndex::from_usize(0x41),
ArgIndex::from_usize(0x75),
),
Instr::OneOp(Opcode::Escp, ArgIndex::from_usize(0x08)),
Instr::OneOp(Opcode::Stoe, ArgIndex::from_usize(0x26)),
Instr::TwoOp(
Opcode::Phdl,
ArgIndex::from_usize(0x12),
ArgIndex::from_usize(0x14),
),
Instr::OneOp(Opcode::Btr, ArgIndex::from_usize(0x10)),
Instr::ZeroOp(Opcode::Exst),
Instr::ZeroOp(Opcode::Argb),
Instr::ZeroOp(Opcode::Targ),
Instr::ZeroOp(Opcode::Tcan),
Instr::ZeroOp(Opcode::Jmps),
Instr::OneOp(Opcode::Prl, ArgIndex::from_usize(0xa4)),
Instr::TwoOp(
Opcode::Pdrl,
ArgIndex::from_usize(0xc1),
ArgIndex::from_usize(0xc4),
),
Instr::OneOp(Opcode::Lbrt, ArgIndex::from_usize(0x2d)),
];
#[test]
fn parse_instructions() {
let mut iter = BufferIterator::new(INSTRUCTIONS_BYTES);
for true_instr in INSTRUCTIONS {
let read_instr = Instr::parse(&mut iter, kerbalobjects::ksm::IntSize::One).unwrap();
assert_eq!(*true_instr, read_instr);
}
}
#[test]
fn parse_wider_indices() {
let bytes = &[
0x4c, 0x00, 0x03, 0x00, 0x08, 0x58, 0x08, 0x01, 0x71, 0x59, 0x21, 0x00, 0x00, 0x00, ];
let instructions = &[
Instr::TwoOp(
Opcode::Call,
ArgIndex::from_usize(0x0003),
ArgIndex::from_usize(0x0008),
),
Instr::OneOp(Opcode::Stol, ArgIndex::from_usize(0x080171)),
Instr::OneOp(Opcode::Stog, ArgIndex::from_usize(0x21000000)),
];
let int_sizes = &[IntSize::Two, IntSize::Three, IntSize::Four];
let mut iter = BufferIterator::new(bytes);
for (true_instr, int_size) in instructions.iter().zip(int_sizes) {
let read_instr = Instr::parse(&mut iter, *int_size).unwrap();
assert_eq!(*true_instr, read_instr);
}
}