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") }