olympia_derive 0.3.0

Olympia is a gameboy emulator and toolkit, intended to run as a native or web assembly application targeting a cycle count accurate emulation. olympia_derive provides a couple of proc macros used for olympia implementation.
Documentation
extern crate alloc;

use olympia_core::address;
use olympia_core::disasm::Disassemble;
use olympia_core::instructions::{
    AppendedParam, ConstantParam, ExtensionType, Instruction, InstructionOpcode, ParamDefinition,
    ParamPosition, ParamType,
};
use olympia_core::registers::WordRegister;
use olympia_derive::OlympiaInstruction;

#[derive(PartialEq, Eq, Debug, OlympiaInstruction)]
#[olympia(opcode = 0x1111_1000, label = "LD")]
struct LoadStackOffset {
    #[olympia(dest, constant(WordRegister::HL))]
    dest: WordRegister,
    #[olympia(src, constant(WordRegister::SP))]
    base: WordRegister,
    #[olympia(addsrc)]
    value: address::AddressOffset,
}

#[test]
fn three_arg_definition() {
    let definition = LoadStackOffset::definition();
    assert_eq!(definition.label, "LD");
    assert_eq!(definition.opcodes, &[0xF8]);
    assert_eq!(definition.extension_type, ExtensionType::None);

    assert_eq!(
        definition.params,
        &[
            ParamDefinition {
                pos: ParamPosition::Dest,
                param_type: ParamType::Constant(ConstantParam::WordRegister(WordRegister::HL)),
            },
            ParamDefinition {
                pos: ParamPosition::Src,
                param_type: ParamType::Constant(ConstantParam::WordRegister(WordRegister::SP)),
            },
            ParamDefinition {
                pos: ParamPosition::AddSrc,
                param_type: ParamType::Appended(AppendedParam::AddressOffset),
            }
        ]
    );
}

#[test]
fn three_arg_expansion() {
    let opcode = LoadStackOffsetOpcode::from_opcode(0xF8);

    assert_eq!(
        opcode.build_instruction(&mut vec![0xFE].into_iter()),
        LoadStackOffset {
            dest: WordRegister::HL,
            base: WordRegister::SP,
            value: address::AddressOffset(-2)
        }
    );
}

#[test]
fn three_arg_disasm() {
    let op = LoadStackOffset {
        dest: WordRegister::HL,
        base: WordRegister::SP,
        value: address::AddressOffset(-2),
    };

    assert_eq!(op.disassemble(), "LD HL, SP + -2h")
}