implement post-inc/dec as part of ld
This commit is contained in:
parent
003daaf7a1
commit
74b823aad6
46
src/emu.rs
46
src/emu.rs
|
|
@ -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 (val, src_adr) = match src {
|
||||
ValSrc::Reg(i) => (self.reg[i as usize], i as usize),
|
||||
ValSrc::Direct => (self.mem[pc + 1], 0),
|
||||
let (src_ref, src_adr) = match src {
|
||||
ValSrc::Reg(i) => (&mut self.reg[i as usize], i as usize),
|
||||
ValSrc::Direct => (&mut self.mem[pc + 1], 0),
|
||||
ValSrc::Mem(ref src) => match src {
|
||||
AddrLoc::Reg(reg) => {
|
||||
let mem_loc = self.reg[*reg] as usize;
|
||||
(self.mem[mem_loc], mem_loc)
|
||||
(&mut self.mem[mem_loc], mem_loc)
|
||||
}
|
||||
AddrLoc::Direct => todo!(),
|
||||
}
|
||||
ValSrc::HMem(_) => todo!(),
|
||||
};
|
||||
|
||||
let val = *src_ref;
|
||||
let src_str = src.repr(src_adr, val);
|
||||
|
||||
let (dst_ref, dst_adr) = match dst {
|
||||
ValSrc::Mem(ref src) => match src {
|
||||
AddrLoc::Direct => {
|
||||
let adr = self.read16(pc) as usize;
|
||||
(&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 {
|
||||
AddrLoc::Direct => {
|
||||
|
|
@ -144,10 +150,16 @@ impl GameBoy {
|
|||
};
|
||||
|
||||
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) {
|
||||
|
|
@ -280,14 +292,8 @@ impl GameBoy {
|
|||
self.reg[reg as usize] -= 1;
|
||||
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),
|
||||
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) => {
|
||||
let v = match src {
|
||||
ValSrc::Reg(r) => self.reg[r],
|
||||
|
|
@ -302,10 +308,12 @@ impl GameBoy {
|
|||
ValSrc::Direct => self.mem[pc+1],
|
||||
_ => panic!("invalid command")
|
||||
};
|
||||
|
||||
let dst = &mut self.reg[Register::A];
|
||||
match bit_op {
|
||||
BitOp::Or => self.reg[Register::A] |= v,
|
||||
BitOp::And => self.reg[Register::A] &= v,
|
||||
BitOp::Xor => self.reg[Register::A] ^= v,
|
||||
BitOp::Or => *dst |= v,
|
||||
BitOp::And => *dst &= v,
|
||||
BitOp::Xor => *dst ^= v,
|
||||
}
|
||||
println!("{bit_op:?} {src:?}");
|
||||
}
|
||||
|
|
|
|||
45
src/op.rs
45
src/op.rs
|
|
@ -21,10 +21,8 @@ pub enum Instr {
|
|||
Pop(Register),
|
||||
|
||||
// Load
|
||||
Ld(ValSrc, ValSrc),
|
||||
Ld(ValSrc, ValSrc, PostOp),
|
||||
Ld16(ValSrc, ValSrc),
|
||||
LdInc(ValSrc), // loads into A
|
||||
LdDec(ValSrc), // loads into A
|
||||
|
||||
// Arith
|
||||
// TODO can we do Inc16/Inc8 with one via Register::WIDE
|
||||
|
|
@ -42,6 +40,13 @@ pub enum Instr {
|
|||
Ret,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PostOp {
|
||||
None,
|
||||
Inc(Register),
|
||||
Dec(Register)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AddrLoc {
|
||||
Reg(Register),
|
||||
|
|
@ -58,20 +63,18 @@ pub enum ValSrc {
|
|||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum Register {
|
||||
A,
|
||||
F,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
H,
|
||||
L,
|
||||
A, F,
|
||||
B, C,
|
||||
D, E,
|
||||
H, L,
|
||||
|
||||
// Double Width
|
||||
AF,
|
||||
BC,
|
||||
DE,
|
||||
HL,
|
||||
|
||||
// Misc
|
||||
SP,
|
||||
}
|
||||
|
||||
|
|
@ -196,10 +199,18 @@ impl TryFrom<u8> for Operation {
|
|||
0b11_001_101 => (Call, 6, 3),
|
||||
0b11_001_001 => (Ret, 4, 1),
|
||||
0b11_110_011 => (Di, 1, 1),
|
||||
0b11_101_010 => (Ld(Mem(AddrLoc::Direct), Reg(A)), 4, 3),
|
||||
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),
|
||||
0b11_101_010 =>
|
||||
(Ld(Mem(AddrLoc::Direct), Reg(A), PostOp::None), 4, 3),
|
||||
0b11_100_000 =>
|
||||
(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_101_110 => (Bit(Xor, 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 => {
|
||||
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 => {
|
||||
let dst = Register::try_from((value & T1_MSK) >> 3)?;
|
||||
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 => {
|
||||
let reg = match payload(value) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue