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 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:?}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
src/op.rs
45
src/op.rs
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue