implement post-inc/dec as part of ld

This commit is contained in:
45Tatami 2024-04-12 19:27:29 +02:00
parent 003daaf7a1
commit 74b823aad6
2 changed files with 55 additions and 36 deletions

View File

@ -108,29 +108,35 @@ impl GameBoy {
} }
} }
fn op_ld(&mut self, dst: ValSrc, src: ValSrc, modifier: i8) { fn op_ld(&mut self, dst: ValSrc, src: ValSrc, postOp: PostOp) {
let pc = self.pc as usize; let pc = self.pc as usize;
let (val, src_adr) = match src { let (src_ref, src_adr) = match src {
ValSrc::Reg(i) => (self.reg[i as usize], i as usize), ValSrc::Reg(i) => (&mut self.reg[i as usize], i as usize),
ValSrc::Direct => (self.mem[pc + 1], 0), ValSrc::Direct => (&mut self.mem[pc + 1], 0),
ValSrc::Mem(ref src) => match src { ValSrc::Mem(ref src) => match src {
AddrLoc::Reg(reg) => { AddrLoc::Reg(reg) => {
let mem_loc = self.reg[*reg] as usize; let mem_loc = self.reg[*reg] as usize;
(self.mem[mem_loc], mem_loc) (&mut self.mem[mem_loc], mem_loc)
} }
AddrLoc::Direct => todo!(), AddrLoc::Direct => todo!(),
} }
ValSrc::HMem(_) => todo!(), ValSrc::HMem(_) => todo!(),
}; };
let val = *src_ref;
let src_str = src.repr(src_adr, val);
let (dst_ref, dst_adr) = match dst { let (dst_ref, dst_adr) = match dst {
ValSrc::Mem(ref src) => match src { ValSrc::Mem(ref src) => match src {
AddrLoc::Direct => { AddrLoc::Direct => {
let adr = self.read16(pc) as usize; let adr = self.read16(pc) as usize;
(&mut self.mem[adr], adr) (&mut self.mem[adr], adr)
} }
_ => todo!(), AddrLoc::Reg(reg) => {
let adr = self.reg[*reg] as usize;
(&mut self.mem[adr], adr)
}
}, },
ValSrc::HMem(ref src) => match src { ValSrc::HMem(ref src) => match src {
AddrLoc::Direct => { AddrLoc::Direct => {
@ -144,10 +150,16 @@ impl GameBoy {
}; };
let dst_str = dst.repr(dst_adr, *dst_ref); let dst_str = dst.repr(dst_adr, *dst_ref);
let src_str = src.repr(src_adr, val);
println!("ld {dst_str} <- {src_str} + {modifier}");
*dst_ref = (val as i16 + modifier as i16) as u8; println!("ld {dst_str} <- {src_str}; post: {postOp:?}");
*dst_ref = val;
match postOp {
PostOp::None => (),
PostOp::Inc(reg) => self.reg[reg] += 1,
PostOp::Dec(reg) => self.reg[reg] -= 1,
}
} }
fn op_ld16(&mut self, dst: ValSrc, src: ValSrc) { fn op_ld16(&mut self, dst: ValSrc, src: ValSrc) {
@ -280,14 +292,8 @@ impl GameBoy {
self.reg[reg as usize] -= 1; self.reg[reg as usize] -= 1;
println!("Dec Reg({reg:#04b})"); println!("Dec Reg({reg:#04b})");
} }
Ld(dst, src) => self.op_ld(dst, src, 0), Ld(dst, src, postOp) => self.op_ld(dst, src, postOp),
Ld16(dst, src) => self.op_ld16(dst, src), Ld16(dst, src) => self.op_ld16(dst, src),
LdInc(src) => {
self.op_ld(ValSrc::Reg(Register::A), src, 1)
}
LdDec(src) => {
self.op_ld(ValSrc::Reg(Register::A), src, -1)
}
Bit(bit_op, src) => { Bit(bit_op, src) => {
let v = match src { let v = match src {
ValSrc::Reg(r) => self.reg[r], ValSrc::Reg(r) => self.reg[r],
@ -302,10 +308,12 @@ impl GameBoy {
ValSrc::Direct => self.mem[pc+1], ValSrc::Direct => self.mem[pc+1],
_ => panic!("invalid command") _ => panic!("invalid command")
}; };
let dst = &mut self.reg[Register::A];
match bit_op { match bit_op {
BitOp::Or => self.reg[Register::A] |= v, BitOp::Or => *dst |= v,
BitOp::And => self.reg[Register::A] &= v, BitOp::And => *dst &= v,
BitOp::Xor => self.reg[Register::A] ^= v, BitOp::Xor => *dst ^= v,
} }
println!("{bit_op:?} {src:?}"); println!("{bit_op:?} {src:?}");
} }

View File

@ -21,10 +21,8 @@ pub enum Instr {
Pop(Register), Pop(Register),
// Load // Load
Ld(ValSrc, ValSrc), Ld(ValSrc, ValSrc, PostOp),
Ld16(ValSrc, ValSrc), Ld16(ValSrc, ValSrc),
LdInc(ValSrc), // loads into A
LdDec(ValSrc), // loads into A
// Arith // Arith
// TODO can we do Inc16/Inc8 with one via Register::WIDE // TODO can we do Inc16/Inc8 with one via Register::WIDE
@ -42,6 +40,13 @@ pub enum Instr {
Ret, Ret,
} }
#[derive(Debug)]
pub enum PostOp {
None,
Inc(Register),
Dec(Register)
}
#[derive(Debug)] #[derive(Debug)]
pub enum AddrLoc { pub enum AddrLoc {
Reg(Register), Reg(Register),
@ -58,20 +63,18 @@ pub enum ValSrc {
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum Register { pub enum Register {
A, A, F,
F, B, C,
B, D, E,
C, H, L,
D,
E,
H,
L,
// Double Width
AF, AF,
BC, BC,
DE, DE,
HL, HL,
// Misc
SP, SP,
} }
@ -196,10 +199,18 @@ impl TryFrom<u8> for Operation {
0b11_001_101 => (Call, 6, 3), 0b11_001_101 => (Call, 6, 3),
0b11_001_001 => (Ret, 4, 1), 0b11_001_001 => (Ret, 4, 1),
0b11_110_011 => (Di, 1, 1), 0b11_110_011 => (Di, 1, 1),
0b11_101_010 => (Ld(Mem(AddrLoc::Direct), Reg(A)), 4, 3), 0b11_101_010 =>
0b11_100_000 => (Ld(HMem(AddrLoc::Direct), Reg(A)), 3, 2), (Ld(Mem(AddrLoc::Direct), Reg(A), PostOp::None), 4, 3),
0b00_101_010 => (LdInc(Mem(AddrLoc::Reg(HL))), 2, 1), 0b11_100_000 =>
0b00_111_010 => (LdDec(Mem(AddrLoc::Reg(HL))), 2, 1), (Ld(HMem(AddrLoc::Direct), Reg(A), PostOp::None), 3, 2),
0b00_100_010 =>
(Ld(Mem(AddrLoc::Reg(HL)), Reg(A), PostOp::Inc(HL)), 2, 1),
0b00_101_010 =>
(Ld(Reg(A), Mem(AddrLoc::Reg(HL)), PostOp::Inc(HL)), 2, 1),
0b00_110_010 =>
(Ld(Mem(AddrLoc::Reg(HL)), Reg(A), PostOp::Dec(HL)), 2, 1),
0b00_111_010 =>
(Ld(Reg(A), Mem(AddrLoc::Reg(HL)), PostOp::Dec(HL)), 2, 1),
0b10_110_110 => (Bit(Or, Mem(AddrLoc::Reg(HL))), 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_101_110 => (Bit(Xor, Mem(AddrLoc::Reg(HL))), 2, 1),
0b10_100_110 => (Bit(And, Mem(AddrLoc::Reg(HL))), 2, 1), 0b10_100_110 => (Bit(And, Mem(AddrLoc::Reg(HL))), 2, 1),
@ -229,12 +240,12 @@ impl TryFrom<u8> for Operation {
} }
_ if (value & (HD_MSK | T2_MSK)) == 0b00_000_110 => { _ if (value & (HD_MSK | T2_MSK)) == 0b00_000_110 => {
let reg = Register::try_from((value & T1_MSK) >> 3)?; let reg = Register::try_from((value & T1_MSK) >> 3)?;
(Ld(Reg(reg), Direct), 2, 2) (Ld(Reg(reg), Direct, PostOp::None), 2, 2)
} }
_ if (value & HD_MSK) == 0b01_000_000 => { _ if (value & HD_MSK) == 0b01_000_000 => {
let dst = Register::try_from((value & T1_MSK) >> 3)?; let dst = Register::try_from((value & T1_MSK) >> 3)?;
let src = Register::try_from(value & T2_MSK)?; let src = Register::try_from(value & T2_MSK)?;
(Ld(Reg(dst), Reg(src)), 1, 1) (Ld(Reg(dst), Reg(src), PostOp::None), 1, 1)
} }
_ if (value & (HD_MSK | 0b1_000 | T2_MSK)) == 0b00_000_001 => { _ if (value & (HD_MSK | 0b1_000 | T2_MSK)) == 0b00_000_001 => {
let reg = match payload(value) { let reg = match payload(value) {