diff --git a/src/emu.rs b/src/emu.rs index b0aaaf5..138d885 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -288,7 +288,7 @@ impl GameBoy { LdDec(src) => { self.op_ld(ValSrc::Reg(Register::A), src, -1) } - Or(src) => { + Bit(bit_op, src) => { let v = match src { ValSrc::Reg(r) => self.reg[r], ValSrc::Mem(ref src) => { @@ -302,8 +302,12 @@ impl GameBoy { ValSrc::Direct => self.mem[pc+1], _ => panic!("invalid command") }; - self.reg[Register::A] |= v; - println!("Or {src:?}"); + match bit_op { + BitOp::Or => self.reg[Register::A] |= v, + BitOp::And => self.reg[Register::A] &= v, + BitOp::Xor => self.reg[Register::A] ^= v, + } + println!("{bit_op:?} {src:?}"); } Di => println!("FIXME Di instruction not implemented"), } diff --git a/src/op.rs b/src/op.rs index 84fdf41..06e77f0 100644 --- a/src/op.rs +++ b/src/op.rs @@ -30,7 +30,7 @@ pub enum Instr { // TODO can we do Inc16/Inc8 with one via Register::WIDE Inc(Register), Dec(Register), - Or(ValSrc), // TODO all bit can probably be done with this one + Bit(BitOp, ValSrc), // CPU ctl Di, @@ -169,6 +169,13 @@ impl TryFrom for Register { } } +#[derive(Debug)] +pub enum BitOp { + Or, + And, + Xor +} + fn payload(v: u8) -> u8 { (v & 0b110_000) >> 4 } @@ -180,6 +187,7 @@ impl TryFrom for Operation { use Instr::*; use ValSrc::*; use Register::*; + use BitOp::*; let (inst, cycl, offs) = match value { 0b00_000_000 => (Nop, 1, 1), @@ -192,10 +200,20 @@ impl TryFrom for Operation { 0b11_100_000 => (Ld(HMem(AddrLoc::Direct), Reg(A)), 3, 2), 0b00_101_010 => (LdInc(Mem(AddrLoc::Reg(HL))), 2, 1), 0b00_111_010 => (LdDec(Mem(AddrLoc::Reg(HL))), 2, 1), - 0b10_110_110 => (Or(Mem(AddrLoc::Reg(HL))), 2, 1), - 0b11_110_110 => (Or(Direct), 2, 1), + 0b10_110_110 => (Bit(Or, Mem(AddrLoc::Reg(HL))), 2, 1), + 0b10_101_110 => (Bit(Xor, Mem(AddrLoc::Reg(HL))), 2, 1), + 0b10_100_110 => (Bit(And, Mem(AddrLoc::Reg(HL))), 2, 1), + 0b11_110_110 => (Bit(Or, Direct), 2, 2), // TODO can bit be grouped via HD & T2? + 0b11_101_110 => (Bit(Xor, Direct), 2, 2), + 0b11_100_110 => (Bit(And, Direct), 2, 2), _ if (value & (HD_MSK | T1_MSK) == 0b10_110_000) => { - (Or(Reg(Register::try_from(value & 0b111)?)), 1, 1) + (Bit(Or, Reg(Register::try_from(value & 0b111)?)), 1, 1) + } + _ if (value & (HD_MSK | T1_MSK) == 0b10_101_000) => { + (Bit(Xor, Reg(Register::try_from(value & 0b111)?)), 1, 1) + } + _ if (value & (HD_MSK | T1_MSK) == 0b10_100_000) => { + (Bit(And, Reg(Register::try_from(value & 0b111)?)), 1, 1) } _ if (value & (HD_MSK | 0b1_000 | T2_MSK) == 0b00_000_011) => { (Inc(Register::from16_rep(payload(value))), 2, 1)