refactor: improve opcode length handling
This commit is contained in:
parent
9e199f8a44
commit
a9c1ac65b3
7 changed files with 141 additions and 252 deletions
|
@ -22,6 +22,7 @@ struct OpcodeArgs {
|
|||
pub opcode: LitInt,
|
||||
pub readable: Expr,
|
||||
pub extended: LitBool,
|
||||
pub length: LitInt,
|
||||
pub implementation: Punctuated<OpcodeImpl, syn::Token!(,)>,
|
||||
}
|
||||
|
||||
|
@ -35,21 +36,24 @@ impl Parse for OpcodeArgs {
|
|||
input.parse::<Token![,]>()?;
|
||||
let extended = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let length = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
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::<u8>().expect("Failed to parse opcode as u8");
|
||||
let length = length.base10_parse::<u8>().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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,14 +51,13 @@ pub fn sub(lhs: u8, rhs: u8) -> CarryResult {
|
|||
macro_rules! define_xor_reg {
|
||||
($op:literal, $reg:ident) => {
|
||||
paste::paste! {
|
||||
opcode!([<xor_a_ $reg>], $op, std::concat!("XOR A,",std::stringify!($reg)), false, {
|
||||
opcode!([<xor_a_ $reg>], $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!([<sbc_a_ $reg>], $op, std::concat!("SBC A,", std::stringify!($reg)), false, {
|
||||
opcode!([<sbc_a_ $reg>], $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!([<add_a_ $reg>], $op, std::concat!("ADD A,", std::stringify!($reg)), false, {
|
||||
opcode!([<add_a_ $reg>], $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!([<adc_a_ $reg>], $op, std::concat!("ADC A,", std::stringify!($reg)), false, {
|
||||
opcode!([<adc_a_ $reg>], $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!([<sub_a_ $reg>], $op, std::concat!("SUB A,", std::stringify!($reg)), false, {
|
||||
opcode!([<sub_a_ $reg>], $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!([<inc_ $reg>], $op, std::concat!("INC ", std::stringify!($reg)), false, {
|
||||
opcode!([<inc_ $reg>], $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!([<dec_ $reg>], $op, std::concat!("DEC ", std::stringify!($reg)), false, {
|
||||
opcode!([<dec_ $reg>], $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!([<inc_ $lreg $rreg>], $op, std::concat!("INC ", std::stringify!($lreg), std::stringify!($rreg)), false, {
|
||||
opcode!([<inc_ $lreg $rreg>], $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!([<dec_ $lreg $rreg>], $op, std::concat!("DEC ", std::stringify!($lreg), std::stringify!($rreg)), false, {
|
||||
opcode!([<dec_ $lreg $rreg>], $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!([<cp_ $lreg _ $rreg>], $op, std::concat!("CP ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, {
|
||||
opcode!([<cp_ $lreg _ $rreg>], $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!([<or_a_ $reg>], $op, std::concat!("OR A,", std::stringify!($reg)), false, {
|
||||
opcode!([<or_a_ $reg>], $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!([<and_a_ $reg>], $op, std::concat!("AND A,", std::stringify!($reg)), false, {
|
||||
opcode!([<and_a_ $reg>], $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!([<add_hl_ $lreg $rreg>], $op, std::concat!("ADD HL, ", std::stringify!($lreg), std::stringify!($rreg)), false, {
|
||||
opcode!([<add_hl_ $lreg $rreg>], $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
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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!([<rst_ $addr>], $op, std::concat!("RST ", std::stringify!($addr)), false, {
|
||||
opcode!([<rst_ $addr>], $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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::gameboy::{cpu::CycleResult, Gameboy};
|
|||
macro_rules! define_ld_reg_imm_u16 {
|
||||
($op:literal, $reg:ident) => {
|
||||
paste::paste! {
|
||||
opcode!([<ld_ $reg _imm_u16>], $op, std::concat!("LD ", std::stringify!($reg), ",u16"), false, {
|
||||
opcode!([<ld_ $reg _imm_u16>], $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.[<set_ $reg>](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!([<ld_ $lreg _ $rreg>], $opcode, std::concat!("LD ", std::stringify!($lreg), ",", std::stringify!($rreg)), false, {
|
||||
opcode!([<ld_ $lreg _ $rreg>], $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!([<ld_ $lreg _deref_ $rreg>], $op, std::concat!("LD ", std::stringify!($lreg), ",(", std::stringify!($rreg), ")"), false, {
|
||||
opcode!([<ld_ $lreg _deref_ $rreg>], $op, std::concat!("LD ", std::stringify!($lreg), ",(", std::stringify!($rreg), ")"), false, 1, {
|
||||
0 => {
|
||||
state.cpu_read_u8(state.registers.[<get_ $rreg>]());
|
||||
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!([<ld_ $lreg _imm_u8>], $op, std::concat!("LD ", std::stringify!($lreg), ",u8"), false, {
|
||||
opcode!([<ld_ $lreg _imm_u8>], $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!([<ld_deref_hl_ $lreg>], $op, std::concat!("LD (HL),", std::stringify!($lreg)), false, {
|
||||
opcode!([<ld_deref_hl_ $lreg>], $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_ $reg>], $push_op, std::concat!("PUSH ", std::stringify!($reg)), false, {
|
||||
opcode!([<push_ $reg>], $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.[<get_ $reg>]() as u8);
|
||||
state.registers.opcode_bytecount = Some(1);
|
||||
CycleResult::NeedsMore
|
||||
},
|
||||
3 => {
|
||||
|
@ -465,7 +443,7 @@ macro_rules! define_push_pop_reg {
|
|||
}
|
||||
});
|
||||
|
||||
opcode!([<pop_ $reg>], $pop_op, std::concat!("POP ", std::stringify!($reg)), false, {
|
||||
opcode!([<pop_ $reg>], $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.[<set_ $reg>](val);
|
||||
state.registers.opcode_bytecount = Some(1);
|
||||
CycleResult::Finished
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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!([<bit_ $bit _ $reg>], $op, std::concat!("BIT ", std::stringify!($bit), ",", std::stringify!($reg)), true, {
|
||||
opcode!([<bit_ $bit _ $reg>], $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!([<bit_ $bit _deref_hl>], $op, std::concat!("BIT ", std::stringify!($bit), ",(HL)"), true, {
|
||||
opcode!([<bit_ $bit _deref_hl>], $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!([<rlc_ $reg>], $op, std::concat!("RLC ", std::stringify!($reg)), true, {
|
||||
opcode!([<rlc_ $reg>], $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!([<rrc_ $reg>], $op, std::concat!("RRC ", std::stringify!($reg)), true, {
|
||||
opcode!([<rrc_ $reg>], $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!([<rl_ $reg>], $op, std::concat!("RL ", std::stringify!($reg)), true, {
|
||||
opcode!([<rl_ $reg>], $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!([<sla_ $reg>], $op, std::concat!("SLA ", std::stringify!($reg)), true, {
|
||||
opcode!([<sla_ $reg>], $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!([<sra_ $reg>], $op, std::concat!("SRA ", std::stringify!($reg)), true, {
|
||||
opcode!([<sra_ $reg>], $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!([<swap_ $reg>], $op, std::concat!("SWAP ", std::stringify!($reg)), true, {
|
||||
opcode!([<swap_ $reg>], $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!([<srl_ $reg>], $op, std::concat!("SRL ", std::stringify!($reg)), true, {
|
||||
opcode!([<srl_ $reg>], $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!([<rr_ $reg>], $op, std::concat!("RR ", std::stringify!($reg)), true, {
|
||||
opcode!([<rr_ $reg>], $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!([<res_ $idx _ $reg>], $op, std::concat!("RES ", std::stringify!($idx), ", ", std::stringify!($reg)), true, {
|
||||
opcode!([<res_ $idx _ $reg>], $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!([<res_ $idx _deref_hl>], $op, std::concat!("RES ", std::stringify!($idx), ", (HL)"), true, {
|
||||
opcode!([<res_ $idx _deref_hl>], $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!([<set_ $idx _ $reg>], $op, std::concat!("SET ", std::stringify!($idx), ", ", std::stringify!($reg)), true, {
|
||||
opcode!([<set_ $idx _ $reg>], $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!([<set_ $idx _deref_hl>], $op, std::concat!("SET ", std::stringify!($idx), ", (HL)"), true, {
|
||||
opcode!([<set_ $idx _deref_hl>], $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
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue