From a9c1ac65b3616307ca9998eb739988e22c14c95d Mon Sep 17 00:00:00 2001 From: EliseZeroTwo Date: Sat, 30 Dec 2023 12:27:06 -0700 Subject: [PATCH] refactor: improve opcode length handling --- deemgee-opcode/src/lib.rs | 16 ++- deemgee/src/gameboy/cpu.rs | 8 +- deemgee/src/gameboy/cpu/alu.rs | 126 +++++++-------------- deemgee/src/gameboy/cpu/flow.rs | 120 +++++++------------- deemgee/src/gameboy/cpu/load_store_move.rs | 69 ++++------- deemgee/src/gameboy/cpu/misc.rs | 12 +- deemgee/src/gameboy/cpu/prefixed.rs | 42 +++---- 7 files changed, 141 insertions(+), 252 deletions(-) diff --git a/deemgee-opcode/src/lib.rs b/deemgee-opcode/src/lib.rs index 50809f8..7014dd2 100644 --- a/deemgee-opcode/src/lib.rs +++ b/deemgee-opcode/src/lib.rs @@ -22,6 +22,7 @@ struct OpcodeArgs { pub opcode: LitInt, pub readable: Expr, pub extended: LitBool, + pub length: LitInt, pub implementation: Punctuated, } @@ -35,21 +36,24 @@ impl Parse for OpcodeArgs { input.parse::()?; let extended = input.parse()?; input.parse::()?; + let length = input.parse()?; + input.parse::()?; let implementation_pb; braced!(implementation_pb in input); let implementation = Punctuated::parse_separated_nonempty(&implementation_pb)?; - Ok(Self { name, opcode, readable, extended, implementation }) + Ok(Self { name, opcode, readable, extended, length, implementation }) } } #[proc_macro] pub fn opcode(item: TokenStream) -> TokenStream { - let OpcodeArgs { name, opcode, readable, extended, implementation } = + let OpcodeArgs { name, opcode, readable, extended, length, implementation } = parse_macro_input!(item as OpcodeArgs); let name_s = name.to_string(); let opcode = opcode.base10_parse::().expect("Failed to parse opcode as u8"); + let length = length.base10_parse::().expect("Failed to parse opcode length as u8"); let fn_sig = quote::quote! { pub fn #name(state: &mut Gameboy) -> CycleResult @@ -104,7 +108,13 @@ pub fn opcode(item: TokenStream) -> TokenStream { #fn_sig { #log - #match_statement + let res: CycleResult = #match_statement; + + if res != CycleResult::NeedsMore { + state.registers.opcode_bytecount = Some(#length); + } + + res } }; diff --git a/deemgee/src/gameboy/cpu.rs b/deemgee/src/gameboy/cpu.rs index f91e939..88359ee 100644 --- a/deemgee/src/gameboy/cpu.rs +++ b/deemgee/src/gameboy/cpu.rs @@ -40,7 +40,7 @@ macro_rules! define_flag { pub enum CycleResult { NeedsMore, Finished, - FinishedChangedPc, + FinishedKeepPc, } #[derive(Debug, Default)] @@ -474,15 +474,15 @@ pub fn tick_cpu(state: &mut Gameboy) { result }; - if result == CycleResult::Finished || result == CycleResult::FinishedChangedPc { + if result == CycleResult::Finished || result == CycleResult::FinishedKeepPc { if state.used_halt_bug { state.registers.pc = state.registers.pc.overflowing_add(1).0; } - if result != CycleResult::FinishedChangedPc { + if result == CycleResult::Finished { match state.registers.opcode_bytecount { Some(len) => state.registers.pc = state.registers.pc.overflowing_add(len as u16).0, - None => panic!("Forgot to set opcode len"), + None => unreachable!("opcode len is missing, which should not be possible"), } } diff --git a/deemgee/src/gameboy/cpu/alu.rs b/deemgee/src/gameboy/cpu/alu.rs index fb8ede3..b2e50b0 100644 --- a/deemgee/src/gameboy/cpu/alu.rs +++ b/deemgee/src/gameboy/cpu/alu.rs @@ -51,14 +51,13 @@ pub fn sub(lhs: u8, rhs: u8) -> CarryResult { macro_rules! define_xor_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("XOR A,",std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("XOR A,",std::stringify!($reg)), false, 1, { 0 => { state.registers.a ^= state.registers.$reg; state.registers.set_zero(state.registers.a == 0); state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -74,7 +73,7 @@ define_xor_reg!(0xAB, e); define_xor_reg!(0xAC, h); define_xor_reg!(0xAD, l); -opcode!(xor_a_deref_hl, 0xAE, "XOR A,(HL)", false, { +opcode!(xor_a_deref_hl, 0xAE, "XOR A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -85,12 +84,11 @@ opcode!(xor_a_deref_hl, 0xAE, "XOR A,(HL)", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(xor_a_imm_u8, 0xEE, "XOR A,u8", false, { +opcode!(xor_a_imm_u8, 0xEE, "XOR A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -101,7 +99,6 @@ opcode!(xor_a_imm_u8, 0xEE, "XOR A,u8", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -109,7 +106,7 @@ opcode!(xor_a_imm_u8, 0xEE, "XOR A,u8", false, { macro_rules! define_sbc_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SBC A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("SBC A,", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, carry } = sub_with_carry(state.registers.a, state.registers.$reg, state.registers.get_carry()); @@ -118,7 +115,6 @@ macro_rules! define_sbc_reg { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -134,7 +130,7 @@ define_sbc_reg!(0x9B, e); define_sbc_reg!(0x9C, h); define_sbc_reg!(0x9D, l); -opcode!(sbc_a_deref_hl, 0x9E, "SBC A,(HL)", false, { +opcode!(sbc_a_deref_hl, 0x9E, "SBC A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -151,12 +147,11 @@ opcode!(sbc_a_deref_hl, 0x9E, "SBC A,(HL)", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(sbc_a_imm_u8, 0xDE, "SBC A,u8", false, { +opcode!(sbc_a_imm_u8, 0xDE, "SBC A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -173,7 +168,6 @@ opcode!(sbc_a_imm_u8, 0xDE, "SBC A,u8", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -181,7 +175,7 @@ opcode!(sbc_a_imm_u8, 0xDE, "SBC A,u8", false, { macro_rules! define_add_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("ADD A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("ADD A,", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, carry } = add(state.registers.a, state.registers.$reg); @@ -190,7 +184,6 @@ macro_rules! define_add_reg { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -206,7 +199,7 @@ define_add_reg!(0x83, e); define_add_reg!(0x84, h); define_add_reg!(0x85, l); -opcode!(add_a_deref_hl, 0x86, "ADD A,(HL)", false, { +opcode!(add_a_deref_hl, 0x86, "ADD A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -220,12 +213,11 @@ opcode!(add_a_deref_hl, 0x86, "ADD A,(HL)", false, { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(add_a_imm_u8, 0xC6, "ADD A,u8", false, { +opcode!(add_a_imm_u8, 0xC6, "ADD A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -239,7 +231,6 @@ opcode!(add_a_imm_u8, 0xC6, "ADD A,u8", false, { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -247,7 +238,7 @@ opcode!(add_a_imm_u8, 0xC6, "ADD A,u8", false, { macro_rules! define_adc_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("ADC A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("ADC A,", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, carry } = add_with_carry(state.registers.a, state.registers.$reg, state.registers.get_carry()); @@ -256,7 +247,6 @@ macro_rules! define_adc_reg { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -272,7 +262,7 @@ define_adc_reg!(0x8B, e); define_adc_reg!(0x8C, h); define_adc_reg!(0x8D, l); -opcode!(adc_a_deref_hl, 0x8E, "ADC A,(HL)", false, { +opcode!(adc_a_deref_hl, 0x8E, "ADC A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -289,12 +279,11 @@ opcode!(adc_a_deref_hl, 0x8E, "ADC A,(HL)", false, { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(adc_a_imm_u8, 0xCE, "ADC A,u8", false, { +opcode!(adc_a_imm_u8, 0xCE, "ADC A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -311,7 +300,6 @@ opcode!(adc_a_imm_u8, 0xCE, "ADC A,u8", false, { state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -319,7 +307,7 @@ opcode!(adc_a_imm_u8, 0xCE, "ADC A,u8", false, { macro_rules! define_sub_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SUB A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("SUB A,", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, carry } = sub(state.registers.a, state.registers.$reg); @@ -328,7 +316,6 @@ macro_rules! define_sub_reg { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -344,7 +331,7 @@ define_sub_reg!(0x93, e); define_sub_reg!(0x94, h); define_sub_reg!(0x95, l); -opcode!(sub_a_deref_hl, 0x96, "SUB A,(HL)", false, { +opcode!(sub_a_deref_hl, 0x96, "SUB A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -358,12 +345,11 @@ opcode!(sub_a_deref_hl, 0x96, "SUB A,(HL)", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(sub_a_imm_u8, 0xD6, "SUB A,u8", false, { +opcode!(sub_a_imm_u8, 0xD6, "SUB A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -377,7 +363,6 @@ opcode!(sub_a_imm_u8, 0xD6, "SUB A,u8", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -385,7 +370,7 @@ opcode!(sub_a_imm_u8, 0xD6, "SUB A,u8", false, { macro_rules! define_inc_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("INC ", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("INC ", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, .. } = add( state.registers.$reg, @@ -396,7 +381,6 @@ macro_rules! define_inc_reg { state.registers.set_zero(result == 0); state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -412,7 +396,7 @@ define_inc_reg!(0x24, h); define_inc_reg!(0x2C, l); define_inc_reg!(0x3C, a); -opcode!(inc_deref_hl, 0x34, "INC (HL)", false, { +opcode!(inc_deref_hl, 0x34, "INC (HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -424,7 +408,6 @@ opcode!(inc_deref_hl, 0x34, "INC (HL)", false, { state.registers.set_zero(result == 0); state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); - state.registers.opcode_bytecount = Some(1); CycleResult::NeedsMore }, 2 => { @@ -435,7 +418,7 @@ opcode!(inc_deref_hl, 0x34, "INC (HL)", false, { macro_rules! define_dec_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("DEC ", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("DEC ", std::stringify!($reg)), false, 1, { 0 => { let CarryResult { result, half_carry, .. } = sub( state.registers.$reg, @@ -446,7 +429,6 @@ macro_rules! define_dec_reg { state.registers.set_zero(result == 0); state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -462,7 +444,7 @@ define_dec_reg!(0x25, h); define_dec_reg!(0x2D, l); define_dec_reg!(0x3D, a); -opcode!(dec_deref_hl, 0x35, "DEC (HL)", false, { +opcode!(dec_deref_hl, 0x35, "DEC (HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -474,7 +456,6 @@ opcode!(dec_deref_hl, 0x35, "DEC (HL)", false, { state.registers.set_zero(result == 0); state.registers.set_subtract(false); state.registers.set_half_carry(half_carry); - state.registers.opcode_bytecount = Some(1); CycleResult::NeedsMore }, 2 => { @@ -482,7 +463,7 @@ opcode!(dec_deref_hl, 0x35, "DEC (HL)", false, { } }); -opcode!(rla, 0x17, "RLA", false, { +opcode!(rla, 0x17, "RLA", false, 1, { 0 => { let carry = state.registers.a >> 7 == 1; state.registers.a <<= 1; @@ -496,12 +477,11 @@ opcode!(rla, 0x17, "RLA", false, { state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(rra, 0x1f, "RRA", false, { +opcode!(rra, 0x1f, "RRA", false, 1, { 0 => { let carry = state.registers.a & 0b1 == 1; state.registers.a >>= 1; @@ -515,7 +495,6 @@ opcode!(rra, 0x1f, "RRA", false, { state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -523,7 +502,7 @@ opcode!(rra, 0x1f, "RRA", false, { macro_rules! define_inc_u16_reg { ($op:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("INC ", std::stringify!($lreg), std::stringify!($rreg)), false, { + opcode!([], $op, std::concat!("INC ", std::stringify!($lreg), std::stringify!($rreg)), false, 1, { 0 => { let (res, carry) = state.registers.$rreg.overflowing_add(1); state.registers.$rreg = res; @@ -535,7 +514,6 @@ macro_rules! define_inc_u16_reg { let (res, _) = state.registers.$lreg.overflowing_add(1); state.registers.$lreg = res; } - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -547,14 +525,13 @@ define_inc_u16_reg!(0x03, b, c); define_inc_u16_reg!(0x13, d, e); define_inc_u16_reg!(0x23, h, l); -opcode!(inc_sp, 0x33, "INC SP", false, { +opcode!(inc_sp, 0x33, "INC SP", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { let (res, _) = state.registers.sp.overflowing_add(1); state.registers.sp = res; - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -562,7 +539,7 @@ opcode!(inc_sp, 0x33, "INC SP", false, { macro_rules! define_dec_u16_reg { ($op:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("DEC ", std::stringify!($lreg), std::stringify!($rreg)), false, { + opcode!([], $op, std::concat!("DEC ", std::stringify!($lreg), std::stringify!($rreg)), false, 1, { 0 => { let (res, carry) = state.registers.$rreg.overflowing_sub(1); state.registers.$rreg = res; @@ -574,7 +551,6 @@ macro_rules! define_dec_u16_reg { let (res, _) = state.registers.$lreg.overflowing_sub(1); state.registers.$lreg = res; } - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -586,14 +562,13 @@ define_dec_u16_reg!(0x0B, b, c); define_dec_u16_reg!(0x1B, d, e); define_dec_u16_reg!(0x2B, h, l); -opcode!(dec_sp, 0x3B, "DEC SP", false, { +opcode!(dec_sp, 0x3B, "DEC SP", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { let (res, _) = state.registers.sp.overflowing_sub(1); state.registers.sp = res; - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -601,14 +576,13 @@ opcode!(dec_sp, 0x3B, "DEC SP", false, { macro_rules! define_cp_reg_reg { ($op:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("CP ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, { + opcode!([], $op, std::concat!("CP ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, 1, { 0 => { let CarryResult { result, half_carry, carry } = sub(state.registers.$lreg, state.registers.$rreg); state.registers.set_zero(result == 0); state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -624,7 +598,7 @@ define_cp_reg_reg!(0xBC, a, h); define_cp_reg_reg!(0xBD, a, l); define_cp_reg_reg!(0xBF, a, a); -opcode!(cp_a_imm_u8, 0xFE, "CP A,u8", false, { +opcode!(cp_a_imm_u8, 0xFE, "CP A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -636,12 +610,11 @@ opcode!(cp_a_imm_u8, 0xFE, "CP A,u8", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(cp_a_deref_hl, 0xBE, "CP A,(HL)", false, { +opcode!(cp_a_deref_hl, 0xBE, "CP A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -653,7 +626,6 @@ opcode!(cp_a_deref_hl, 0xBE, "CP A,(HL)", false, { state.registers.set_subtract(true); state.registers.set_half_carry(half_carry); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -661,7 +633,7 @@ opcode!(cp_a_deref_hl, 0xBE, "CP A,(HL)", false, { macro_rules! define_or_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("OR A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("OR A,", std::stringify!($reg)), false, 1, { 0 => { let result = state.registers.a | state.registers.$reg; @@ -670,7 +642,6 @@ macro_rules! define_or_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -686,7 +657,7 @@ define_or_reg!(0xB3, e); define_or_reg!(0xB4, h); define_or_reg!(0xB5, l); -opcode!(or_a_deref_hl, 0xB6, "OR A,(HL)", false, { +opcode!(or_a_deref_hl, 0xB6, "OR A,(HL)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -699,12 +670,11 @@ opcode!(or_a_deref_hl, 0xB6, "OR A,(HL)", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(or_a_imm_u8, 0xF6, "OR A,u8", false, { +opcode!(or_a_imm_u8, 0xF6, "OR A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -717,7 +687,6 @@ opcode!(or_a_imm_u8, 0xF6, "OR A,u8", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -725,7 +694,7 @@ opcode!(or_a_imm_u8, 0xF6, "OR A,u8", false, { macro_rules! define_and_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("AND A,", std::stringify!($reg)), false, { + opcode!([], $op, std::concat!("AND A,", std::stringify!($reg)), false, 1, { 0 => { let result = state.registers.a & state.registers.$reg; @@ -734,7 +703,6 @@ macro_rules! define_and_reg { state.registers.set_subtract(false); state.registers.set_half_carry(true); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -750,7 +718,7 @@ define_and_reg!(0xA3, e); define_and_reg!(0xA4, h); define_and_reg!(0xA5, l); -opcode!(and_a_deref_hl, 0xA6, "AND A,(hl)", false, { +opcode!(and_a_deref_hl, 0xA6, "AND A,(hl)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -763,12 +731,11 @@ opcode!(and_a_deref_hl, 0xA6, "AND A,(hl)", false, { state.registers.set_subtract(false); state.registers.set_half_carry(true); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(and_a_imm_u8, 0xE6, "AND A,u8", false, { +opcode!(and_a_imm_u8, 0xE6, "AND A,u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc + 1); CycleResult::NeedsMore @@ -781,37 +748,33 @@ opcode!(and_a_imm_u8, 0xE6, "AND A,u8", false, { state.registers.set_subtract(false); state.registers.set_half_carry(true); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(cpl, 0x2F, "CPL", false, { +opcode!(cpl, 0x2F, "CPL", false, 1, { 0 => { state.registers.a = !state.registers.a; state.registers.set_subtract(true); state.registers.set_half_carry(true); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ccf, 0x3F, "CCF", false, { +opcode!(ccf, 0x3F, "CCF", false, 1, { 0 => { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(!state.registers.get_carry()); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(scf, 0x37, "SCF", false, { +opcode!(scf, 0x37, "SCF", false, 1, { 0 => { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(true); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -819,7 +782,7 @@ opcode!(scf, 0x37, "SCF", false, { macro_rules! define_add_hl_u16_reg { ($op:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("ADD HL, ", std::stringify!($lreg), std::stringify!($rreg)), false, { + opcode!([], $op, std::concat!("ADD HL, ", std::stringify!($lreg), std::stringify!($rreg)), false, 1, { 0 => { let CarryResult { result, carry, .. } = add(state.registers.l, state.registers.$rreg); state.registers.l = result; @@ -840,7 +803,6 @@ macro_rules! define_add_hl_u16_reg { } state.registers.set_subtract(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -851,7 +813,7 @@ macro_rules! define_add_hl_u16_reg { define_add_hl_u16_reg!(0x09, b, c); define_add_hl_u16_reg!(0x19, d, e); define_add_hl_u16_reg!(0x29, h, l); -opcode!(add_hl_sp, 0x39, "ADD HL, SP", false, { +opcode!(add_hl_sp, 0x39, "ADD HL, SP", false, 1, { 0 => { let CarryResult { result, carry, .. } = add(state.registers.l, state.registers.sp as u8); @@ -873,12 +835,11 @@ opcode!(add_hl_sp, 0x39, "ADD HL, SP", false, { } state.registers.set_subtract(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(rlca, 0x7, "RLCA", false, { +opcode!(rlca, 0x7, "RLCA", false, 1, { 0 => { let carry = state.registers.a >> 7 == 1; state.registers.a <<= 1; @@ -888,12 +849,11 @@ opcode!(rlca, 0x7, "RLCA", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(rrca, 0xF, "RRCA", false, { +opcode!(rrca, 0xF, "RRCA", false, 1, { 0 => { let carry = state.registers.a & 0b1 == 1; state.registers.a >>= 1; @@ -903,12 +863,11 @@ opcode!(rrca, 0xF, "RRCA", false, { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(daa, 0x27, "DAA", false, { +opcode!(daa, 0x27, "DAA", false, 1, { 0 => { let mut value = 0; let mut carry = false; @@ -930,7 +889,6 @@ opcode!(daa, 0x27, "DAA", false, { state.registers.set_half_carry(false); state.registers.set_carry(carry); state.registers.set_zero(state.registers.a == 0); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); diff --git a/deemgee/src/gameboy/cpu/flow.rs b/deemgee/src/gameboy/cpu/flow.rs index dfdb66c..a20a9e2 100644 --- a/deemgee/src/gameboy/cpu/flow.rs +++ b/deemgee/src/gameboy/cpu/flow.rs @@ -3,7 +3,7 @@ use deemgee_opcode::opcode; use super::CycleResult; use crate::gameboy::Gameboy; -opcode!(jr_nz_i8, 0x20, "JR NZ,i8", false, { +opcode!(jr_nz_i8, 0x20, "JR NZ,i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -11,7 +11,6 @@ opcode!(jr_nz_i8, 0x20, "JR NZ,i8", false, { 1 => { if state.registers.get_zero() { state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } else { CycleResult::NeedsMore @@ -26,12 +25,11 @@ opcode!(jr_nz_i8, 0x20, "JR NZ,i8", false, { state.registers.pc = state.registers.pc.overflowing_sub(relative.abs() as u16).0; } - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(jr_nc_i8, 0x30, "JR NC,i8", false, { +opcode!(jr_nc_i8, 0x30, "JR NC,i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -39,7 +37,6 @@ opcode!(jr_nc_i8, 0x30, "JR NC,i8", false, { 1 => { if state.registers.get_carry() { state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } else { CycleResult::NeedsMore @@ -54,12 +51,11 @@ opcode!(jr_nc_i8, 0x30, "JR NC,i8", false, { state.registers.pc = state.registers.pc.overflowing_sub(relative.abs() as u16).0; } - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(jr_z_i8, 0x28, "JR Z,i8", false, { +opcode!(jr_z_i8, 0x28, "JR Z,i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -67,7 +63,6 @@ opcode!(jr_z_i8, 0x28, "JR Z,i8", false, { 1 => { if !state.registers.get_zero() { state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } else { CycleResult::NeedsMore @@ -82,12 +77,11 @@ opcode!(jr_z_i8, 0x28, "JR Z,i8", false, { state.registers.pc = state.registers.pc.overflowing_sub(relative.abs() as u16).0; } - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(jr_c_i8, 0x38, "JR C,i8", false, { +opcode!(jr_c_i8, 0x38, "JR C,i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -95,7 +89,6 @@ opcode!(jr_c_i8, 0x38, "JR C,i8", false, { 1 => { if !state.registers.get_carry() { state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } else { CycleResult::NeedsMore @@ -110,12 +103,11 @@ opcode!(jr_c_i8, 0x38, "JR C,i8", false, { state.registers.pc = state.registers.pc.overflowing_sub(relative.abs() as u16).0; } - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(jr_i8, 0x18, "JR i8", false, { +opcode!(jr_i8, 0x18, "JR i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -132,12 +124,11 @@ opcode!(jr_i8, 0x18, "JR i8", false, { state.registers.pc = state.registers.pc.overflowing_sub(relative.abs() as u16).0; } - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(jp_u16, 0xC3, "JP u16", false, { +opcode!(jp_u16, 0xC3, "JP u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -154,20 +145,18 @@ opcode!(jp_u16, 0xC3, "JP u16", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(jp_hl, 0xE9, "JP HL", false, { +opcode!(jp_hl, 0xE9, "JP HL", false, 1, { 0 => { state.registers.pc = state.registers.get_hl(); - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(jp_nz_u16, 0xC2, "JP NZ,u16", false, { +opcode!(jp_nz_u16, 0xC2, "JP NZ,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -182,7 +171,6 @@ opcode!(jp_nz_u16, 0xC2, "JP NZ,u16", false, { if state.registers.get_zero() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -191,12 +179,11 @@ opcode!(jp_nz_u16, 0xC2, "JP NZ,u16", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(jp_nc_u16, 0xD2, "JP NC,u16", false, { +opcode!(jp_nc_u16, 0xD2, "JP NC,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -220,12 +207,11 @@ opcode!(jp_nc_u16, 0xD2, "JP NC,u16", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(jp_z_u16, 0xCA, "JP Z,u16", false, { +opcode!(jp_z_u16, 0xCA, "JP Z,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -240,7 +226,6 @@ opcode!(jp_z_u16, 0xCA, "JP Z,u16", false, { if !state.registers.get_zero() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -249,12 +234,11 @@ opcode!(jp_z_u16, 0xCA, "JP Z,u16", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(jp_c_u16, 0xDA, "JP C,u16", false, { +opcode!(jp_c_u16, 0xDA, "JP C,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -269,7 +253,6 @@ opcode!(jp_c_u16, 0xDA, "JP C,u16", false, { if !state.registers.get_carry() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -278,12 +261,11 @@ opcode!(jp_c_u16, 0xDA, "JP C,u16", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(call_u16, 0xCD, "CALL u16", false, { +opcode!(call_u16, 0xCD, "CALL u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -308,12 +290,11 @@ opcode!(call_u16, 0xCD, "CALL u16", false, { 5 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(call_nz_u16, 0xC4, "CALL NZ,u16", false, { +opcode!(call_nz_u16, 0xC4, "CALL NZ,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -328,7 +309,6 @@ opcode!(call_nz_u16, 0xC4, "CALL NZ,u16", false, { if state.registers.get_zero() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -345,12 +325,11 @@ opcode!(call_nz_u16, 0xC4, "CALL NZ,u16", false, { 5 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(call_nc_u16, 0xD4, "CALL NC,u16", false, { +opcode!(call_nc_u16, 0xD4, "CALL NC,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -365,7 +344,6 @@ opcode!(call_nc_u16, 0xD4, "CALL NC,u16", false, { if state.registers.get_carry() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -382,12 +360,11 @@ opcode!(call_nc_u16, 0xD4, "CALL NC,u16", false, { 5 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(call_z_u16, 0xCC, "CALL Z,u16", false, { +opcode!(call_z_u16, 0xCC, "CALL Z,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -402,7 +379,6 @@ opcode!(call_z_u16, 0xCC, "CALL Z,u16", false, { if !state.registers.get_zero() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -419,12 +395,11 @@ opcode!(call_z_u16, 0xCC, "CALL Z,u16", false, { 5 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(call_c_u16, 0xDC, "CALL C,u16", false, { +opcode!(call_c_u16, 0xDC, "CALL C,u16", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -439,7 +414,6 @@ opcode!(call_c_u16, 0xDC, "CALL C,u16", false, { if !state.registers.get_carry() { state.registers.take_mem(); state.registers.take_hold(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } else { CycleResult::NeedsMore @@ -456,12 +430,11 @@ opcode!(call_c_u16, 0xDC, "CALL C,u16", false, { 5 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(ret, 0xC9, "RET", false, { +opcode!(ret, 0xC9, "RET", false, 1, { 0 => { state.cpu_pop_stack(); CycleResult::NeedsMore @@ -478,12 +451,11 @@ opcode!(ret, 0xC9, "RET", false, { 3 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(reti, 0xD9, "RETI", false, { +opcode!(reti, 0xD9, "RETI", false, 1, { 0 => { state.cpu_pop_stack(); CycleResult::NeedsMore @@ -501,18 +473,16 @@ opcode!(reti, 0xD9, "RETI", false, { state.interrupts.ime = true; let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(ret_nz, 0xC0, "RET NZ", false, { +opcode!(ret_nz, 0xC0, "RET NZ", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { if state.registers.get_zero() { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } else { state.cpu_pop_stack(); @@ -531,18 +501,16 @@ opcode!(ret_nz, 0xC0, "RET NZ", false, { 4 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(ret_nc, 0xD0, "RET NC", false, { +opcode!(ret_nc, 0xD0, "RET NC", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { if state.registers.get_carry() { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } else { state.cpu_pop_stack(); @@ -561,18 +529,16 @@ opcode!(ret_nc, 0xD0, "RET NC", false, { 4 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(ret_z, 0xC8, "RET Z", false, { +opcode!(ret_z, 0xC8, "RET Z", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { if !state.registers.get_zero() { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } else { state.cpu_pop_stack(); @@ -591,18 +557,16 @@ opcode!(ret_z, 0xC8, "RET Z", false, { 4 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); -opcode!(ret_c, 0xD8, "RET C", false, { +opcode!(ret_c, 0xD8, "RET C", false, 1, { 0 => { CycleResult::NeedsMore }, 1 => { if !state.registers.get_carry() { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } else { state.cpu_pop_stack(); @@ -621,15 +585,14 @@ opcode!(ret_c, 0xD8, "RET C", false, { 4 => { let address = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.pc = address; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); macro_rules! define_rst { ($op:literal, $addr:literal) => { paste::paste! { - opcode!([], $op, std::concat!("RST ", std::stringify!($addr)), false, { + opcode!([], $op, std::concat!("RST ", std::stringify!($addr)), false, 1, { 0 => { CycleResult::NeedsMore }, @@ -643,8 +606,7 @@ macro_rules! define_rst { }, 3 => { state.registers.pc = $addr; - state.registers.opcode_bytecount = Some(0); - CycleResult::Finished + CycleResult::FinishedKeepPc } }); } diff --git a/deemgee/src/gameboy/cpu/load_store_move.rs b/deemgee/src/gameboy/cpu/load_store_move.rs index 729e259..8a39319 100644 --- a/deemgee/src/gameboy/cpu/load_store_move.rs +++ b/deemgee/src/gameboy/cpu/load_store_move.rs @@ -5,7 +5,7 @@ use crate::gameboy::{cpu::CycleResult, Gameboy}; macro_rules! define_ld_reg_imm_u16 { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("LD ", std::stringify!($reg), ",u16"), false, { + opcode!([], $op, std::concat!("LD ", std::stringify!($reg), ",u16"), false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -23,7 +23,6 @@ macro_rules! define_ld_reg_imm_u16 { reg &= 0xFF; reg |= (state.registers.take_mem() as u16) << 8; state.registers.[](reg); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } }); @@ -36,7 +35,7 @@ define_ld_reg_imm_u16!(0x11, de); define_ld_reg_imm_u16!(0x21, hl); define_ld_reg_imm_u16!(0x31, sp); -opcode!(ld_sp_hl, 0xF9, "LD SP,HL", false, { +opcode!(ld_sp_hl, 0xF9, "LD SP,HL", false, 1, { 0 => { state.registers.sp &= 0xFF00; state.registers.sp |= state.registers.l as u16; @@ -45,12 +44,11 @@ opcode!(ld_sp_hl, 0xF9, "LD SP,HL", false, { 1 => { state.registers.sp &= 0xFF; state.registers.sp |= (state.registers.h as u16) << 8; - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } }); -opcode!(ld_deref_imm_u16_sp, 0x08, "LD (u16),SP", false, { +opcode!(ld_deref_imm_u16_sp, 0x08, "LD (u16),SP", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -70,7 +68,6 @@ opcode!(ld_deref_imm_u16_sp, 0x08, "LD (u16),SP", false, { 3 => { let addr = state.registers.take_hold().overflowing_add(1).0; state.cpu_write_u8(addr, (state.registers.sp >> 8) as u8); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } }); @@ -78,11 +75,10 @@ opcode!(ld_deref_imm_u16_sp, 0x08, "LD (u16),SP", false, { macro_rules! define_ld_reg_reg { ($opcode:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $opcode, std::concat!("LD ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, { + opcode!([], $opcode, std::concat!("LD ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, 1, { 0 => { let res = state.registers.$rreg; state.registers.$lreg = res; - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -143,14 +139,13 @@ define_ld_reg_reg!(0x7F, a, a); macro_rules! define_ld_reg_deref { ($op:literal, $lreg:ident, $rreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("LD ", std::stringify!($lreg), ",(", std::stringify!($rreg), ")"), false, { + opcode!([], $op, std::concat!("LD ", std::stringify!($lreg), ",(", std::stringify!($rreg), ")"), false, 1, { 0 => { state.cpu_read_u8(state.registers.[]()); CycleResult::NeedsMore }, 1 => { state.registers.$lreg = state.registers.take_mem(); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); @@ -168,29 +163,27 @@ define_ld_reg_deref!(0x7E, a, hl); define_ld_reg_deref!(0x0A, a, bc); define_ld_reg_deref!(0x1A, a, de); -opcode!(ld_deref_bc_a, 0x02, "LD (BC),A", false, { +opcode!(ld_deref_bc_a, 0x02, "LD (BC),A", false, 1, { 0 => { state.cpu_write_u8(state.registers.get_bc(), state.registers.a); CycleResult::NeedsMore }, 1 => { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_deref_de_a, 0x12, "LD (DE),A", false, { +opcode!(ld_deref_de_a, 0x12, "LD (DE),A", false, 1, { 0 => { state.cpu_write_u8(state.registers.get_de(), state.registers.a); CycleResult::NeedsMore }, 1 => { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_hl_plus_a, 0x22, "LD (HL+),A", false, { +opcode!(ld_hl_plus_a, 0x22, "LD (HL+),A", false, 1, { 0 => { state.cpu_write_u8(state.registers.get_hl(), state.registers.a); CycleResult::NeedsMore @@ -198,12 +191,11 @@ opcode!(ld_hl_plus_a, 0x22, "LD (HL+),A", false, { 1 => { let reg = state.registers.get_hl().overflowing_add(1).0; state.registers.set_hl(reg); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_hl_minus_a, 0x32, "LD (HL-),A", false, { +opcode!(ld_hl_minus_a, 0x32, "LD (HL-),A", false, 1, { 0 => { state.cpu_write_u8(state.registers.get_hl(), state.registers.a); CycleResult::NeedsMore @@ -211,12 +203,11 @@ opcode!(ld_hl_minus_a, 0x32, "LD (HL-),A", false, { 1 => { let reg = state.registers.get_hl().overflowing_sub(1).0; state.registers.set_hl(reg); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_a_hl_plus, 0x2A, "LD A,(HL+)", false, { +opcode!(ld_a_hl_plus, 0x2A, "LD A,(HL+)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -225,12 +216,11 @@ opcode!(ld_a_hl_plus, 0x2A, "LD A,(HL+)", false, { state.registers.a = state.registers.take_mem(); let reg = state.registers.get_hl().overflowing_add(1).0; state.registers.set_hl(reg); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_a_hl_minus, 0x3A, "LD A,(HL-)", false, { +opcode!(ld_a_hl_minus, 0x3A, "LD A,(HL-)", false, 1, { 0 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -239,12 +229,11 @@ opcode!(ld_a_hl_minus, 0x3A, "LD A,(HL-)", false, { state.registers.a = state.registers.take_mem(); let reg = state.registers.get_hl().overflowing_sub(1).0; state.registers.set_hl(reg); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ld_hl_sp_i8, 0xF8, "LD HL,SP+i8", false, { +opcode!(ld_hl_sp_i8, 0xF8, "LD HL,SP+i8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -266,7 +255,6 @@ opcode!(ld_hl_sp_i8, 0xF8, "LD HL,SP+i8", false, { CycleResult::NeedsMore }, 2 => { - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -274,14 +262,13 @@ opcode!(ld_hl_sp_i8, 0xF8, "LD HL,SP+i8", false, { macro_rules! define_ld_reg_imm_u8 { ($op:literal, $lreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("LD ", std::stringify!($lreg), ",u8"), false, { + opcode!([], $op, std::concat!("LD ", std::stringify!($lreg), ",u8"), false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore }, 1 => { state.registers.$lreg = state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -297,7 +284,7 @@ define_ld_reg_imm_u8!(0x26, h); define_ld_reg_imm_u8!(0x2E, l); define_ld_reg_imm_u8!(0x3E, a); -opcode!(ld_deref_hl_imm_u8, 0x36, "LD (HL),u8", false, { +opcode!(ld_deref_hl_imm_u8, 0x36, "LD (HL),u8", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -305,7 +292,6 @@ opcode!(ld_deref_hl_imm_u8, 0x36, "LD (HL),u8", false, { 1 => { let imm = state.registers.take_mem(); state.cpu_write_u8(state.registers.get_hl(), imm); - state.registers.opcode_bytecount = Some(2); CycleResult::NeedsMore }, 2 => { @@ -313,7 +299,7 @@ opcode!(ld_deref_hl_imm_u8, 0x36, "LD (HL),u8", false, { } }); -opcode!(ldh_a_imm_u8, 0xF0, "LDH A,(u8)", false, { +opcode!(ldh_a_imm_u8, 0xF0, "LDH A,(u8)", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -326,12 +312,11 @@ opcode!(ldh_a_imm_u8, 0xF0, "LDH A,(u8)", false, { }, 2 => { state.registers.a = state.registers.take_mem(); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); -opcode!(ldh_imm_u8_a, 0xE0, "LDH (u8),A", false, { +opcode!(ldh_imm_u8_a, 0xE0, "LDH (u8),A", false, 2, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -340,7 +325,6 @@ opcode!(ldh_imm_u8_a, 0xE0, "LDH (u8),A", false, { let imm = state.registers.take_mem(); let addr = 0xFF00u16 | imm as u16; state.cpu_write_u8(addr, state.registers.a); - state.registers.opcode_bytecount = Some(2); CycleResult::NeedsMore }, 2 => { @@ -348,7 +332,7 @@ opcode!(ldh_imm_u8_a, 0xE0, "LDH (u8),A", false, { } }); -opcode!(ldh_a_deref_c, 0xF2, "LDH A,(C)", false, { +opcode!(ldh_a_deref_c, 0xF2, "LDH A,(C)", false, 1, { 0 => { let imm = state.registers.c; let addr = 0xFF00u16 | imm as u16; @@ -357,16 +341,14 @@ opcode!(ldh_a_deref_c, 0xF2, "LDH A,(C)", false, { }, 1 => { state.registers.a = state.registers.take_mem(); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ldh_deref_c_a, 0xE2, "LDH (C),A", false, { +opcode!(ldh_deref_c_a, 0xE2, "LDH (C),A", false, 1, { 0 => { let addr = 0xFF00u16 | state.registers.c as u16; state.cpu_write_u8(addr, state.registers.a); - state.registers.opcode_bytecount = Some(1); CycleResult::NeedsMore }, 1 => { @@ -374,7 +356,7 @@ opcode!(ldh_deref_c_a, 0xE2, "LDH (C),A", false, { } }); -opcode!(ld_a_deref_imm_u16, 0xFA, "LD A,(u16)", false, { +opcode!(ld_a_deref_imm_u16, 0xFA, "LD A,(u16)", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -392,12 +374,11 @@ opcode!(ld_a_deref_imm_u16, 0xFA, "LD A,(u16)", false, { }, 3 => { state.registers.a = state.registers.take_mem(); - state.registers.opcode_bytecount = Some(3); CycleResult::Finished } }); -opcode!(ld_deref_imm_u16_a, 0xEA, "LD (u16),A", false, { +opcode!(ld_deref_imm_u16_a, 0xEA, "LD (u16),A", false, 3, { 0 => { state.cpu_read_u8(state.registers.pc.overflowing_add(1).0); CycleResult::NeedsMore @@ -411,7 +392,6 @@ opcode!(ld_deref_imm_u16_a, 0xEA, "LD (u16),A", false, { 2 => { let addr = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.cpu_write_u8(addr, state.registers.a); - state.registers.opcode_bytecount = Some(3); CycleResult::NeedsMore }, 3 => { @@ -422,10 +402,9 @@ opcode!(ld_deref_imm_u16_a, 0xEA, "LD (u16),A", false, { macro_rules! define_ld_deref_hl_reg { ($op:literal, $lreg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("LD (HL),", std::stringify!($lreg)), false, { + opcode!([], $op, std::concat!("LD (HL),", std::stringify!($lreg)), false, 1, { 0 => { state.cpu_write_u8(state.registers.get_hl(), state.registers.$lreg); - state.registers.opcode_bytecount = Some(1); CycleResult::NeedsMore }, 1 => { @@ -447,7 +426,7 @@ define_ld_deref_hl_reg!(0x77, a); macro_rules! define_push_pop_reg { ($push_op:literal, $pop_op:literal, $reg:ident) => { paste::paste! { - opcode!([], $push_op, std::concat!("PUSH ", std::stringify!($reg)), false, { + opcode!([], $push_op, std::concat!("PUSH ", std::stringify!($reg)), false, 1, { 0 => { CycleResult::NeedsMore }, @@ -457,7 +436,6 @@ macro_rules! define_push_pop_reg { }, 2 => { state.cpu_push_stack(state.registers.[]() as u8); - state.registers.opcode_bytecount = Some(1); CycleResult::NeedsMore }, 3 => { @@ -465,7 +443,7 @@ macro_rules! define_push_pop_reg { } }); - opcode!([], $pop_op, std::concat!("POP ", std::stringify!($reg)), false, { + opcode!([], $pop_op, std::concat!("POP ", std::stringify!($reg)), false, 1, { 0 => { state.cpu_pop_stack(); CycleResult::NeedsMore @@ -479,7 +457,6 @@ macro_rules! define_push_pop_reg { 2 => { let val = (state.registers.take_mem() as u16) << 8 | state.registers.take_hold(); state.registers.[](val); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); diff --git a/deemgee/src/gameboy/cpu/misc.rs b/deemgee/src/gameboy/cpu/misc.rs index 345e028..61c2be6 100644 --- a/deemgee/src/gameboy/cpu/misc.rs +++ b/deemgee/src/gameboy/cpu/misc.rs @@ -3,37 +3,33 @@ use deemgee_opcode::opcode; use super::CycleResult; use crate::gameboy::Gameboy; -opcode!(nop, 0x00, "NOP", false, { +opcode!(nop, 0x00, "NOP", false, 1, { 0 => { - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(di, 0xF3, "DI", false, { +opcode!(di, 0xF3, "DI", false, 1, { 0 => { state.interrupts.cpu_set_ime(false); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(ei, 0xFB, "EI", false, { +opcode!(ei, 0xFB, "EI", false, 1, { 0 => { state.interrupts.cpu_set_ime(true); - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); -opcode!(halt, 0x76, "HALT", false, { +opcode!(halt, 0x76, "HALT", false, 1, { 0 => { if !state.interrupts.ime && (state.interrupts.interrupt_enable & state.interrupts.interrupt_flag & 0x1F != 0) { state.halt_bug = true; } else { state.halt = true; } - state.registers.opcode_bytecount = Some(1); CycleResult::Finished } }); diff --git a/deemgee/src/gameboy/cpu/prefixed.rs b/deemgee/src/gameboy/cpu/prefixed.rs index 83d3c0f..b11c77c 100644 --- a/deemgee/src/gameboy/cpu/prefixed.rs +++ b/deemgee/src/gameboy/cpu/prefixed.rs @@ -279,12 +279,11 @@ pub fn prefixed_handler(state: &mut Gameboy) -> CycleResult { macro_rules! define_bit_reg { ($op:literal, $bit:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("BIT ", std::stringify!($bit), ",", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("BIT ", std::stringify!($bit), ",", std::stringify!($reg)), true, 2, { 1 => { state.registers.set_zero(state.registers.$reg & (1 << $bit) == 0); state.registers.set_subtract(false); state.registers.set_half_carry(true); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -352,7 +351,7 @@ define_bit_reg!(0x7f, 7, a); macro_rules! define_bit_deref_hl { ($op:literal, $bit:literal) => { paste::paste! { - opcode!([], $op, std::concat!("BIT ", std::stringify!($bit), ",(HL)"), true, { + opcode!([], $op, std::concat!("BIT ", std::stringify!($bit), ",(HL)"), true, 2, { 1 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -362,7 +361,6 @@ macro_rules! define_bit_deref_hl { state.registers.set_zero(mem_read & (1 << $bit) == 0); state.registers.set_subtract(false); state.registers.set_half_carry(true); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -382,7 +380,7 @@ define_bit_deref_hl!(0x7e, 7); macro_rules! define_rlc_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("RLC ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("RLC ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg >> 7 == 1; state.registers.$reg <<= 1; @@ -392,7 +390,6 @@ macro_rules! define_rlc_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -411,7 +408,7 @@ define_rlc_reg!(0x07, a); macro_rules! define_rrc_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("RRC ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("RRC ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg & 0b1 == 1; state.registers.$reg >>= 1; @@ -421,7 +418,6 @@ macro_rules! define_rrc_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -440,7 +436,7 @@ define_rrc_reg!(0x0F, a); macro_rules! define_rl_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("RL ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("RL ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg >> 7 == 1; state.registers.$reg <<= 1; @@ -453,7 +449,6 @@ macro_rules! define_rl_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -472,7 +467,7 @@ define_rl_reg!(0x17, a); macro_rules! define_sla_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SLA ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("SLA ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg & (0b1 << 7) == 1; state.registers.$reg = ((state.registers.$reg as i8) << 1) as u8; @@ -481,7 +476,6 @@ macro_rules! define_sla_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -500,7 +494,7 @@ define_sla_reg!(0x27, a); macro_rules! define_sra_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SRA ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("SRA ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg & 0b1 == 1; state.registers.$reg = ((state.registers.$reg as i8) >> 1) as u8; @@ -509,7 +503,6 @@ macro_rules! define_sra_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -528,7 +521,7 @@ define_sra_reg!(0x2F, a); macro_rules! define_swap_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SWAP ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("SWAP ", std::stringify!($reg)), true, 2, { 1 => { state.registers.$reg = (state.registers.$reg >> 4) | (state.registers.$reg << 4); @@ -536,7 +529,6 @@ macro_rules! define_swap_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(false); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -555,7 +547,7 @@ define_swap_reg!(0x37, a); macro_rules! define_srl_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SRL ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("SRL ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg & 0b1 == 1; state.registers.$reg >>= 1; @@ -564,7 +556,6 @@ macro_rules! define_srl_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -583,7 +574,7 @@ define_srl_reg!(0x3f, a); macro_rules! define_rr_reg { ($op:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("RR ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("RR ", std::stringify!($reg)), true, 2, { 1 => { let carry = state.registers.$reg & 0b1 == 1; state.registers.$reg >>= 1; @@ -592,7 +583,6 @@ macro_rules! define_rr_reg { state.registers.set_subtract(false); state.registers.set_half_carry(false); state.registers.set_carry(carry); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -611,10 +601,9 @@ define_rr_reg!(0x1f, a); macro_rules! define_res_idx_reg { ($op:literal, $idx:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("RES ", std::stringify!($idx), ", ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("RES ", std::stringify!($idx), ", ", std::stringify!($reg)), true, 2, { 1 => { state.registers.$reg &= !(1u8 << $idx); - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -682,7 +671,7 @@ define_res_idx_reg!(0xbf, 7, a); macro_rules! define_res_idx_deref_hl { ($op:literal, $idx:literal) => { paste::paste! { - opcode!([], $op, std::concat!("RES ", std::stringify!($idx), ", (HL)"), true, { + opcode!([], $op, std::concat!("RES ", std::stringify!($idx), ", (HL)"), true, 2, { 1 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -693,7 +682,6 @@ macro_rules! define_res_idx_deref_hl { CycleResult::NeedsMore }, 3 => { - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -713,10 +701,9 @@ define_res_idx_deref_hl!(0xBE, 7); macro_rules! define_set_idx_reg { ($op:literal, $idx:literal, $reg:ident) => { paste::paste! { - opcode!([], $op, std::concat!("SET ", std::stringify!($idx), ", ", std::stringify!($reg)), true, { + opcode!([], $op, std::concat!("SET ", std::stringify!($idx), ", ", std::stringify!($reg)), true, 2, { 1 => { state.registers.$reg |= 1u8 << $idx; - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } }); @@ -784,7 +771,7 @@ define_set_idx_reg!(0xff, 7, a); macro_rules! define_set_idx_deref_hl { ($op:literal, $idx:literal) => { paste::paste! { - opcode!([], $op, std::concat!("SET ", std::stringify!($idx), ", (HL)"), true, { + opcode!([], $op, std::concat!("SET ", std::stringify!($idx), ", (HL)"), true, 2, { 1 => { state.cpu_read_u8(state.registers.get_hl()); CycleResult::NeedsMore @@ -795,7 +782,6 @@ macro_rules! define_set_idx_deref_hl { CycleResult::NeedsMore }, 3 => { - state.registers.opcode_bytecount = Some(2); CycleResult::Finished } });