superh 0.2.3

Disassembler for the SuperH (SH) instruction set (SH1/2/3/4)
Documentation
use superh::{
    Data, DecodeOptions, DecodeResult, Ins, ParseEndian, ParseMode, ParsedValue, Parser, Reg,
};

#[test]
fn instruction_items_include_word_offset_address_and_size() {
    let bytes = [0xe0, 0x01, 0x00, 0x09];
    let mut parser =
        Parser::new(&bytes, ParseMode::Instruction, ParseEndian::Big, DecodeOptions::default());
    parser.set_address(0x8c01_0000);
    let first = parser.next().expect("first instruction");
    assert_eq!((first.offset, first.address, first.size), (0, 0x8c01_0000, 2));
    assert_eq!(
        first.value,
        ParsedValue::Instruction {
            word: 0xe001,
            result: DecodeResult::Instruction(Ins::MovImmRn { rn: Reg::R0, imm: 1 }),
        }
    );
    let second = parser.next().expect("second instruction");
    assert_eq!((second.offset, second.address), (2, 0x8c01_0002));
}

#[test]
fn parser_honors_little_endian_words() {
    let bytes = [0x01, 0xe0];
    let item =
        Parser::new(&bytes, ParseMode::Instruction, ParseEndian::Little, DecodeOptions::default())
            .next()
            .expect("instruction");
    assert!(matches!(item.value, ParsedValue::Instruction { word: 0xe001, .. }));
}

#[test]
fn odd_trailing_instruction_byte_is_data() {
    let bytes = [0x00, 0x09, 0xff];
    let mut parser =
        Parser::new(&bytes, ParseMode::Instruction, ParseEndian::Big, DecodeOptions::default());
    parser.next();
    let tail = parser.next().expect("trailing byte");
    assert_eq!(tail.value, ParsedValue::Data(Data::Byte(0xff)));
    assert_eq!((tail.offset, tail.size), (2, 1));
}

#[test]
fn data_alignment_follows_mapped_address() {
    let bytes = [0xaa, 0xbb, 0x12, 0x34, 0x56, 0x78];
    let mut parser =
        Parser::new(&bytes, ParseMode::Data, ParseEndian::Big, DecodeOptions::default());
    parser.set_address(0x8c01_0002);
    assert_eq!(parser.next().expect("word").value, ParsedValue::Data(Data::Word(0xaabb)));
    assert_eq!(parser.next().expect("long").value, ParsedValue::Data(Data::Long(0x1234_5678)));
}

#[test]
fn seeking_preserves_the_address_mapping() {
    let bytes = [0; 8];
    let mut parser =
        Parser::new(&bytes, ParseMode::Data, ParseEndian::Big, DecodeOptions::default());
    parser.set_address(0x1000);
    parser.goto_offset(6);
    assert_eq!((parser.offset(), parser.address()), (6, 0x1006));
    parser.jump(-4);
    assert_eq!((parser.offset(), parser.address()), (2, 0x1002));
    parser.jump(100);
    assert_eq!((parser.offset(), parser.address()), (8, 0x1008));
}

#[test]
fn data_has_its_own_display_adapter() {
    assert_eq!(Data::Long(0x1234_5678).display().to_string(), ".long 0x12345678");
}