Implement Instructions and rename enums
This commit is contained in:
parent
0be0030ed7
commit
cb365fd932
|
@ -57,7 +57,7 @@ impl Cpu {
|
||||||
Register::E => self.reg.e = value,
|
Register::E => self.reg.e = value,
|
||||||
Register::H => self.reg.h = value,
|
Register::H => self.reg.h = value,
|
||||||
Register::L => self.reg.l = value,
|
Register::L => self.reg.l = value,
|
||||||
Register::Flags => self.reg.a = value.into(),
|
Register::Flag => self.reg.a = value.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl Cpu {
|
||||||
Register::E => self.reg.e,
|
Register::E => self.reg.e,
|
||||||
Register::H => self.reg.h,
|
Register::H => self.reg.h,
|
||||||
Register::L => self.reg.l,
|
Register::L => self.reg.l,
|
||||||
Register::Flags => self.flags.into(),
|
Register::Flag => self.flags.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ pub enum Register {
|
||||||
E,
|
E,
|
||||||
H,
|
H,
|
||||||
L,
|
L,
|
||||||
Flags,
|
Flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RegisterPair {
|
pub enum RegisterPair {
|
||||||
|
|
|
@ -5,8 +5,8 @@ pub enum Instruction {
|
||||||
STOP,
|
STOP,
|
||||||
JR(JumpCondition, i8),
|
JR(JumpCondition, i8),
|
||||||
ADD(MATHTarget, MATHTarget),
|
ADD(MATHTarget, MATHTarget),
|
||||||
INC(AllRegisters),
|
INC(Registers),
|
||||||
DEC(AllRegisters),
|
DEC(Registers),
|
||||||
RLCA,
|
RLCA,
|
||||||
RRCA,
|
RRCA,
|
||||||
RLA,
|
RLA,
|
||||||
|
@ -58,28 +58,28 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
Cycles(12)
|
Cycles(12)
|
||||||
}
|
}
|
||||||
(LDTarget::IndirectRegister(pair), LDTarget::Register(InstrRegisters::A)) => {
|
(LDTarget::IndirectRegister(pair), LDTarget::Register(InstrRegister::A)) => {
|
||||||
let a = cpu.register(Register::A);
|
let a = cpu.register(Register::A);
|
||||||
|
|
||||||
match pair {
|
match pair {
|
||||||
InstrRegisterPairs::BC => {
|
InstrRegisterPair::BC => {
|
||||||
// LD (BC), A | Put A into memory address BC
|
// LD (BC), A | Put A into memory address BC
|
||||||
let addr = cpu.register_pair(RegisterPair::BC);
|
let addr = cpu.register_pair(RegisterPair::BC);
|
||||||
cpu.write_byte(addr, a);
|
cpu.write_byte(addr, a);
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::DE => {
|
InstrRegisterPair::DE => {
|
||||||
// LD (DE), A | Put A into memory address DE
|
// LD (DE), A | Put A into memory address DE
|
||||||
let addr = cpu.register_pair(RegisterPair::DE);
|
let addr = cpu.register_pair(RegisterPair::DE);
|
||||||
cpu.write_byte(addr, a);
|
cpu.write_byte(addr, a);
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::IncrementHL => {
|
InstrRegisterPair::IncrementHL => {
|
||||||
// LD (HL+), A | Put A into memory address HL, then increment HL
|
// LD (HL+), A | Put A into memory address HL, then increment HL
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.write_byte(addr, a);
|
cpu.write_byte(addr, a);
|
||||||
|
|
||||||
cpu.set_register_pair(RegisterPair::HL, addr + 1);
|
cpu.set_register_pair(RegisterPair::HL, addr + 1);
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::DecrementHL => {
|
InstrRegisterPair::DecrementHL => {
|
||||||
// LD (HL-), A | Put A into memory address HL, then decrement HL
|
// LD (HL-), A | Put A into memory address HL, then decrement HL
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.write_byte(addr, a);
|
cpu.write_byte(addr, a);
|
||||||
|
@ -90,26 +90,26 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
Cycles(8)
|
Cycles(8)
|
||||||
}
|
}
|
||||||
(LDTarget::Register(InstrRegisters::A), LDTarget::IndirectRegister(pair)) => {
|
(LDTarget::Register(InstrRegister::A), LDTarget::IndirectRegister(pair)) => {
|
||||||
match pair {
|
match pair {
|
||||||
InstrRegisterPairs::BC => {
|
InstrRegisterPair::BC => {
|
||||||
// LD A, (BC) | Put value at address BC into A
|
// LD A, (BC) | Put value at address BC into A
|
||||||
let addr = cpu.register_pair(RegisterPair::BC);
|
let addr = cpu.register_pair(RegisterPair::BC);
|
||||||
cpu.set_register(Register::A, cpu.read_byte(addr));
|
cpu.set_register(Register::A, cpu.read_byte(addr));
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::DE => {
|
InstrRegisterPair::DE => {
|
||||||
// LD A, (DE) | Put value at address DE into A
|
// LD A, (DE) | Put value at address DE into A
|
||||||
let addr = cpu.register_pair(RegisterPair::DE);
|
let addr = cpu.register_pair(RegisterPair::DE);
|
||||||
cpu.set_register(Register::A, cpu.read_byte(addr));
|
cpu.set_register(Register::A, cpu.read_byte(addr));
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::IncrementHL => {
|
InstrRegisterPair::IncrementHL => {
|
||||||
// LD A, (HL+) | Put value at address HL into A, then increment HL
|
// LD A, (HL+) | Put value at address HL into A, then increment HL
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.set_register(Register::A, cpu.read_byte(addr));
|
cpu.set_register(Register::A, cpu.read_byte(addr));
|
||||||
|
|
||||||
cpu.set_register_pair(RegisterPair::HL, addr + 1);
|
cpu.set_register_pair(RegisterPair::HL, addr + 1);
|
||||||
}
|
}
|
||||||
InstrRegisterPairs::DecrementHL => {
|
InstrRegisterPair::DecrementHL => {
|
||||||
// LD A, (HL-) | Put value at address HL into A, then increment HL
|
// LD A, (HL-) | Put value at address HL into A, then increment HL
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.set_register(Register::A, cpu.read_byte(addr));
|
cpu.set_register(Register::A, cpu.read_byte(addr));
|
||||||
|
@ -125,40 +125,40 @@ impl Instruction {
|
||||||
let cycles: Cycles;
|
let cycles: Cycles;
|
||||||
|
|
||||||
match reg {
|
match reg {
|
||||||
InstrRegisters::B => {
|
InstrRegister::B => {
|
||||||
cpu.set_register(Register::B, n);
|
cpu.set_register(Register::B, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::C => {
|
InstrRegister::C => {
|
||||||
cpu.set_register(Register::C, n);
|
cpu.set_register(Register::C, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::D => {
|
InstrRegister::D => {
|
||||||
cpu.set_register(Register::D, n);
|
cpu.set_register(Register::D, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::E => {
|
InstrRegister::E => {
|
||||||
cpu.set_register(Register::E, n);
|
cpu.set_register(Register::E, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::H => {
|
InstrRegister::H => {
|
||||||
cpu.set_register(Register::H, n);
|
cpu.set_register(Register::H, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::L => {
|
InstrRegister::L => {
|
||||||
cpu.set_register(Register::L, n);
|
cpu.set_register(Register::L, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectHL => {
|
InstrRegister::IndirectHL => {
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.write_byte(addr, n);
|
cpu.write_byte(addr, n);
|
||||||
cycles = Cycles(12);
|
cycles = Cycles(12);
|
||||||
}
|
}
|
||||||
InstrRegisters::A => {
|
InstrRegister::A => {
|
||||||
cpu.set_register(Register::A, n);
|
cpu.set_register(Register::A, n);
|
||||||
cycles = Cycles(8);
|
cycles = Cycles(8);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectC => unreachable!(),
|
InstrRegister::IndirectC => unreachable!(),
|
||||||
}
|
}
|
||||||
cycles
|
cycles
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ impl Instruction {
|
||||||
// JR cc[y - 4], d | If condition is true, then add d to current address and jump
|
// JR cc[y - 4], d | If condition is true, then add d to current address and jump
|
||||||
// JR d | Add d to current address and jump
|
// JR d | Add d to current address and jump
|
||||||
let prev = cpu.register_pair(RegisterPair::PC);
|
let prev = cpu.register_pair(RegisterPair::PC);
|
||||||
let flags: Flags = cpu.register(Register::Flags).into();
|
let flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let new_address = (prev as i16 + offset as i16) as u16;
|
let new_address = (prev as i16 + offset as i16) as u16;
|
||||||
|
|
||||||
match cond {
|
match cond {
|
||||||
|
@ -212,7 +212,7 @@ impl Instruction {
|
||||||
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
|
(MATHTarget::RegisterPair(RegisterPair::HL), MATHTarget::RegisterPair(pair)) => {
|
||||||
// ADD HL, rp[p] | add register pair to HL.
|
// ADD HL, rp[p] | add register pair to HL.
|
||||||
let hl = cpu.register_pair(RegisterPair::HL);
|
let hl = cpu.register_pair(RegisterPair::HL);
|
||||||
let mut flags: Flags = cpu.register(Register::Flags).into();
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let sum;
|
let sum;
|
||||||
|
|
||||||
match pair {
|
match pair {
|
||||||
|
@ -233,13 +233,13 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
cpu.set_register(Register::Flags, flags.into());
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
cpu.set_register_pair(RegisterPair::HL, sum);
|
cpu.set_register_pair(RegisterPair::HL, sum);
|
||||||
Cycles(8)
|
Cycles(8)
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
Instruction::INC(AllRegisters::Word(pair)) => {
|
Instruction::INC(Registers::Word(pair)) => {
|
||||||
// INC rp[p] | Increment Register Pair
|
// INC rp[p] | Increment Register Pair
|
||||||
match pair {
|
match pair {
|
||||||
RegisterPair::BC => {
|
RegisterPair::BC => {
|
||||||
|
@ -262,58 +262,58 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
Cycles(8)
|
Cycles(8)
|
||||||
}
|
}
|
||||||
Instruction::INC(AllRegisters::Byte(reg)) => {
|
Instruction::INC(Registers::Byte(reg)) => {
|
||||||
// INC r[y] | Increment Register
|
// INC r[y] | Increment Register
|
||||||
let mut flags: Flags = cpu.register(Register::Flags).into();
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let cycles: Cycles;
|
let cycles: Cycles;
|
||||||
|
|
||||||
match reg {
|
match reg {
|
||||||
InstrRegisters::B => {
|
InstrRegister::B => {
|
||||||
let b = cpu.register(Register::B);
|
let b = cpu.register(Register::B);
|
||||||
cpu.set_register(Register::B, Self::inc_register(b, &mut flags));
|
cpu.set_register(Register::B, Self::inc_register(b, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::C => {
|
InstrRegister::C => {
|
||||||
let c = cpu.register(Register::C);
|
let c = cpu.register(Register::C);
|
||||||
cpu.set_register(Register::C, Self::inc_register(c, &mut flags));
|
cpu.set_register(Register::C, Self::inc_register(c, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::D => {
|
InstrRegister::D => {
|
||||||
let d = cpu.register(Register::D);
|
let d = cpu.register(Register::D);
|
||||||
cpu.set_register(Register::D, Self::inc_register(d, &mut flags));
|
cpu.set_register(Register::D, Self::inc_register(d, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::E => {
|
InstrRegister::E => {
|
||||||
let e = cpu.register(Register::E);
|
let e = cpu.register(Register::E);
|
||||||
cpu.set_register(Register::E, Self::inc_register(e, &mut flags));
|
cpu.set_register(Register::E, Self::inc_register(e, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::H => {
|
InstrRegister::H => {
|
||||||
let h = cpu.register(Register::H);
|
let h = cpu.register(Register::H);
|
||||||
cpu.set_register(Register::H, Self::inc_register(h, &mut flags));
|
cpu.set_register(Register::H, Self::inc_register(h, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::L => {
|
InstrRegister::L => {
|
||||||
let l = cpu.register(Register::L);
|
let l = cpu.register(Register::L);
|
||||||
cpu.set_register(Register::L, Self::inc_register(l, &mut flags));
|
cpu.set_register(Register::L, Self::inc_register(l, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectHL => {
|
InstrRegister::IndirectHL => {
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.write_byte(addr, Self::inc_register(cpu.read_byte(addr), &mut flags));
|
cpu.write_byte(addr, Self::inc_register(cpu.read_byte(addr), &mut flags));
|
||||||
cycles = Cycles(12);
|
cycles = Cycles(12);
|
||||||
}
|
}
|
||||||
InstrRegisters::A => {
|
InstrRegister::A => {
|
||||||
let a = cpu.register(Register::A);
|
let a = cpu.register(Register::A);
|
||||||
cpu.set_register(Register::A, Self::inc_register(a, &mut flags));
|
cpu.set_register(Register::A, Self::inc_register(a, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectC => unreachable!(),
|
InstrRegister::IndirectC => unreachable!(),
|
||||||
}
|
}
|
||||||
cpu.set_register(Register::Flags, flags.into());
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
cycles
|
cycles
|
||||||
}
|
}
|
||||||
Instruction::DEC(AllRegisters::Word(pair)) => {
|
Instruction::DEC(Registers::Word(pair)) => {
|
||||||
// DEC rp[p] | Decrement Register Pair
|
// DEC rp[p] | Decrement Register Pair
|
||||||
match pair {
|
match pair {
|
||||||
RegisterPair::BC => {
|
RegisterPair::BC => {
|
||||||
|
@ -336,89 +336,154 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
Cycles(8)
|
Cycles(8)
|
||||||
}
|
}
|
||||||
Instruction::DEC(AllRegisters::Byte(reg)) => {
|
Instruction::DEC(Registers::Byte(reg)) => {
|
||||||
// DEC r[y] | Decrement Register
|
// DEC r[y] | Decrement Register
|
||||||
let mut flags: Flags = cpu.register(Register::Flags).into();
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let cycles: Cycles;
|
let cycles: Cycles;
|
||||||
|
|
||||||
match reg {
|
match reg {
|
||||||
InstrRegisters::B => {
|
InstrRegister::B => {
|
||||||
let b = cpu.register(Register::B);
|
let b = cpu.register(Register::B);
|
||||||
cpu.set_register(Register::B, Self::dec_register(b, &mut flags));
|
cpu.set_register(Register::B, Self::dec_register(b, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::C => {
|
InstrRegister::C => {
|
||||||
let c = cpu.register(Register::C);
|
let c = cpu.register(Register::C);
|
||||||
cpu.set_register(Register::C, Self::dec_register(c, &mut flags));
|
cpu.set_register(Register::C, Self::dec_register(c, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::D => {
|
InstrRegister::D => {
|
||||||
let d = cpu.register(Register::D);
|
let d = cpu.register(Register::D);
|
||||||
cpu.set_register(Register::D, Self::dec_register(d, &mut flags));
|
cpu.set_register(Register::D, Self::dec_register(d, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::E => {
|
InstrRegister::E => {
|
||||||
let e = cpu.register(Register::E);
|
let e = cpu.register(Register::E);
|
||||||
cpu.set_register(Register::E, Self::dec_register(e, &mut flags));
|
cpu.set_register(Register::E, Self::dec_register(e, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::H => {
|
InstrRegister::H => {
|
||||||
let h = cpu.register(Register::H);
|
let h = cpu.register(Register::H);
|
||||||
cpu.set_register(Register::H, Self::dec_register(h, &mut flags));
|
cpu.set_register(Register::H, Self::dec_register(h, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::L => {
|
InstrRegister::L => {
|
||||||
let l = cpu.register(Register::L);
|
let l = cpu.register(Register::L);
|
||||||
cpu.set_register(Register::L, Self::dec_register(l, &mut flags));
|
cpu.set_register(Register::L, Self::dec_register(l, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectHL => {
|
InstrRegister::IndirectHL => {
|
||||||
let addr = cpu.register_pair(RegisterPair::HL);
|
let addr = cpu.register_pair(RegisterPair::HL);
|
||||||
cpu.write_byte(addr, Self::dec_register(cpu.read_byte(addr), &mut flags));
|
cpu.write_byte(addr, Self::dec_register(cpu.read_byte(addr), &mut flags));
|
||||||
cycles = Cycles(12);
|
cycles = Cycles(12);
|
||||||
}
|
}
|
||||||
InstrRegisters::A => {
|
InstrRegister::A => {
|
||||||
let a = cpu.register(Register::A);
|
let a = cpu.register(Register::A);
|
||||||
cpu.set_register(Register::A, Self::dec_register(a, &mut flags));
|
cpu.set_register(Register::A, Self::dec_register(a, &mut flags));
|
||||||
cycles = Cycles(4);
|
cycles = Cycles(4);
|
||||||
}
|
}
|
||||||
InstrRegisters::IndirectC => unreachable!(),
|
InstrRegister::IndirectC => unreachable!(),
|
||||||
}
|
}
|
||||||
cpu.set_register(Register::Flags, flags.into());
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
cycles
|
cycles
|
||||||
}
|
}
|
||||||
Instruction::RLCA => {
|
Instruction::RLCA => {
|
||||||
// FIXME: Pretty sure this is an incorrect implementation
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let mut flags: Flags = cpu.register(Register::Flags).into();
|
|
||||||
|
|
||||||
let a = cpu.register(Register::A);
|
let a = cpu.register(Register::A);
|
||||||
let carry_bit = (a & 0x80) >> 7;
|
let cache = a >> 7; // get the 7th bit (this will be the carry bit + the one that is wrapped around)
|
||||||
let new_a = a << 1;
|
let rot_a = (a << 1) | (cache << 0); // (rotate a left), then set the first bit (which will be a 0 by default)
|
||||||
|
|
||||||
flags.z = 0 == new_a;
|
flags.z = false;
|
||||||
flags.n = false;
|
flags.n = false;
|
||||||
flags.h = false;
|
flags.h = false;
|
||||||
flags.c = carry_bit == 0x01;
|
flags.c = cache == 0x01;
|
||||||
|
|
||||||
cpu.set_register(Register::A, new_a);
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
cpu.set_register(Register::A, rot_a);
|
||||||
Cycles(4)
|
Cycles(4)
|
||||||
}
|
}
|
||||||
Instruction::RRCA => {
|
Instruction::RRCA => {
|
||||||
// FIXME: Pretty sure this is an incorrect implementation
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
let mut flags: Flags = cpu.register(Register::Flags).into();
|
|
||||||
|
|
||||||
let a = cpu.register(Register::A);
|
let a = cpu.register(Register::A);
|
||||||
let carry_bit = a & 0x01;
|
let cache = a & 0x01; // RLCA but the other way around
|
||||||
let new_a = a >> 1;
|
let rot_a = (a >> 1) | (cache << 7);
|
||||||
|
|
||||||
flags.z = new_a == 0;
|
flags.z = false;
|
||||||
flags.n = false;
|
flags.n = false;
|
||||||
flags.h = false;
|
flags.h = false;
|
||||||
flags.c = carry_bit == 0x01;
|
flags.c = cache == 0x01;
|
||||||
|
|
||||||
cpu.set_register(Register::A, new_a);
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
cpu.set_register(Register::A, rot_a);
|
||||||
Cycles(4)
|
Cycles(4)
|
||||||
}
|
}
|
||||||
|
Instruction::RLA => {
|
||||||
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
|
|
||||||
|
let a = cpu.register(Register::A);
|
||||||
|
let cache = a >> 7;
|
||||||
|
let rot_a = (a << 1) | ((flags.c as u8) << 0);
|
||||||
|
|
||||||
|
flags.z = false;
|
||||||
|
flags.n = false;
|
||||||
|
flags.h = false;
|
||||||
|
flags.c = cache == 0x01;
|
||||||
|
|
||||||
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
cpu.set_register(Register::A, rot_a);
|
||||||
|
Cycles(4)
|
||||||
|
}
|
||||||
|
Instruction::RRA => {
|
||||||
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
|
|
||||||
|
let a = cpu.register(Register::A);
|
||||||
|
let cache = a & 0x01;
|
||||||
|
let rot_a = (a >> 1) | ((flags.c as u8) << 7);
|
||||||
|
|
||||||
|
flags.z = false;
|
||||||
|
flags.n = false;
|
||||||
|
flags.h = false;
|
||||||
|
flags.c = cache == 0x01;
|
||||||
|
|
||||||
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
cpu.set_register(Register::A, rot_a);
|
||||||
|
Cycles(4)
|
||||||
|
}
|
||||||
|
Instruction::DAA => unimplemented!(),
|
||||||
|
Instruction::CPL => {
|
||||||
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
|
let a = cpu.register(Register::A);
|
||||||
|
|
||||||
|
flags.n = true;
|
||||||
|
flags.h = true;
|
||||||
|
|
||||||
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
cpu.set_register(Register::A, !a); // Bitwise not is ! instead of ~
|
||||||
|
Cycles(4)
|
||||||
|
}
|
||||||
|
Instruction::SCF => {
|
||||||
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
|
|
||||||
|
flags.n = false;
|
||||||
|
flags.h = false;
|
||||||
|
flags.c = true;
|
||||||
|
|
||||||
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
Cycles(4)
|
||||||
|
}
|
||||||
|
Instruction::CCF => {
|
||||||
|
let mut flags: Flags = cpu.register(Register::Flag).into();
|
||||||
|
|
||||||
|
flags.n = false;
|
||||||
|
flags.h = false;
|
||||||
|
flags.c = !flags.c;
|
||||||
|
|
||||||
|
cpu.set_register(Register::Flag, flags.into());
|
||||||
|
Cycles(4)
|
||||||
|
}
|
||||||
|
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,59 +568,59 @@ impl Instruction {
|
||||||
),
|
),
|
||||||
(0, 2, 0, _, 0) => Instruction::LD(
|
(0, 2, 0, _, 0) => Instruction::LD(
|
||||||
// LD (BC), A
|
// LD (BC), A
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::BC),
|
LDTarget::IndirectRegister(InstrRegisterPair::BC),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(0, 2, 0, _, 1) => Instruction::LD(
|
(0, 2, 0, _, 1) => Instruction::LD(
|
||||||
// LD (DE), A
|
// LD (DE), A
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::DE),
|
LDTarget::IndirectRegister(InstrRegisterPair::DE),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(0, 2, 1, _, 0) => Instruction::LD(
|
(0, 2, 1, _, 0) => Instruction::LD(
|
||||||
// LD A, (BC)
|
// LD A, (BC)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::BC),
|
LDTarget::IndirectRegister(InstrRegisterPair::BC),
|
||||||
),
|
),
|
||||||
(0, 2, 1, _, 1) => Instruction::LD(
|
(0, 2, 1, _, 1) => Instruction::LD(
|
||||||
// LD A, (DE)
|
// LD A, (DE)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::DE),
|
LDTarget::IndirectRegister(InstrRegisterPair::DE),
|
||||||
),
|
),
|
||||||
(0, 2, 0, _, 2) => Instruction::LD(
|
(0, 2, 0, _, 2) => Instruction::LD(
|
||||||
// LD (HL+), A
|
// LD (HL+), A
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::IncrementHL),
|
LDTarget::IndirectRegister(InstrRegisterPair::IncrementHL),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(0, 2, 0, _, 3) => Instruction::LD(
|
(0, 2, 0, _, 3) => Instruction::LD(
|
||||||
// LD (HL-), A
|
// LD (HL-), A
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::DecrementHL),
|
LDTarget::IndirectRegister(InstrRegisterPair::DecrementHL),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(0, 2, 1, _, 2) => Instruction::LD(
|
(0, 2, 1, _, 2) => Instruction::LD(
|
||||||
// LD A, (HL+)
|
// LD A, (HL+)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::IncrementHL),
|
LDTarget::IndirectRegister(InstrRegisterPair::IncrementHL),
|
||||||
),
|
),
|
||||||
(0, 2, 1, _, 3) => Instruction::LD(
|
(0, 2, 1, _, 3) => Instruction::LD(
|
||||||
// LD A, (HL-)
|
// LD A, (HL-)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::IndirectRegister(InstrRegisterPairs::DecrementHL),
|
LDTarget::IndirectRegister(InstrRegisterPair::DecrementHL),
|
||||||
),
|
),
|
||||||
(0, 3, 0, _, _) => Instruction::INC(
|
(0, 3, 0, _, _) => Instruction::INC(
|
||||||
// INC rp[p]
|
// INC rp[p]
|
||||||
AllRegisters::Word(Table::rp(p)),
|
Registers::Word(Table::rp(p)),
|
||||||
),
|
),
|
||||||
(0, 3, 1, _, _) => Instruction::DEC(
|
(0, 3, 1, _, _) => Instruction::DEC(
|
||||||
// DEC rp[p]
|
// DEC rp[p]
|
||||||
AllRegisters::Word(Table::rp(p)),
|
Registers::Word(Table::rp(p)),
|
||||||
),
|
),
|
||||||
(0, 4, _, _, _) => Instruction::INC(
|
(0, 4, _, _, _) => Instruction::INC(
|
||||||
// INC r[y]
|
// INC r[y]
|
||||||
AllRegisters::Byte(Table::r(y)),
|
Registers::Byte(Table::r(y)),
|
||||||
),
|
),
|
||||||
(0, 5, _, _, _) => Instruction::DEC(
|
(0, 5, _, _, _) => Instruction::DEC(
|
||||||
// DEC r[y]
|
// DEC r[y]
|
||||||
AllRegisters::Byte(Table::r(y)),
|
Registers::Byte(Table::r(y)),
|
||||||
),
|
),
|
||||||
(0, 6, _, _, _) => Instruction::LD(
|
(0, 6, _, _, _) => Instruction::LD(
|
||||||
// LD r[y], n
|
// LD r[y], n
|
||||||
|
@ -581,7 +646,7 @@ impl Instruction {
|
||||||
(3, 0, _, 4, _) => Instruction::LD(
|
(3, 0, _, 4, _) => Instruction::LD(
|
||||||
// LD (0xFF00 + n), A
|
// LD (0xFF00 + n), A
|
||||||
LDTarget::ByteAtAddress(0xFF00 + (n as u16)), // TODO: Do we want to do any calculations here?
|
LDTarget::ByteAtAddress(0xFF00 + (n as u16)), // TODO: Do we want to do any calculations here?
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(3, 0, _, 5, _) => Instruction::ADD(
|
(3, 0, _, 5, _) => Instruction::ADD(
|
||||||
// ADD SP, d
|
// ADD SP, d
|
||||||
|
@ -590,7 +655,7 @@ impl Instruction {
|
||||||
),
|
),
|
||||||
(3, 0, _, 6, _) => Instruction::LD(
|
(3, 0, _, 6, _) => Instruction::LD(
|
||||||
// LD A, (0xFF00 + n)
|
// LD A, (0xFF00 + n)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::ByteAtAddress(0xFF00 + (n as u16)), // TODO: DO we want to do any calculations here?
|
LDTarget::ByteAtAddress(0xFF00 + (n as u16)), // TODO: DO we want to do any calculations here?
|
||||||
),
|
),
|
||||||
(3, 0, _, 7, _) => Instruction::LDHL(n as i8), // LD HL, SP + d
|
(3, 0, _, 7, _) => Instruction::LDHL(n as i8), // LD HL, SP + d
|
||||||
|
@ -614,22 +679,22 @@ impl Instruction {
|
||||||
),
|
),
|
||||||
(3, 2, _, 4, _) => Instruction::LD(
|
(3, 2, _, 4, _) => Instruction::LD(
|
||||||
// LD (0xFF00 + C) ,A
|
// LD (0xFF00 + C) ,A
|
||||||
LDTarget::Register(InstrRegisters::IndirectC),
|
LDTarget::Register(InstrRegister::IndirectC),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(3, 2, _, 5, _) => Instruction::LD(
|
(3, 2, _, 5, _) => Instruction::LD(
|
||||||
// LD (nn), A
|
// LD (nn), A
|
||||||
LDTarget::ByteAtAddress(nn),
|
LDTarget::ByteAtAddress(nn),
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
),
|
),
|
||||||
(3, 2, _, 6, _) => Instruction::LD(
|
(3, 2, _, 6, _) => Instruction::LD(
|
||||||
// LD A, (0xFF00 + C)
|
// LD A, (0xFF00 + C)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::Register(InstrRegisters::IndirectC),
|
LDTarget::Register(InstrRegister::IndirectC),
|
||||||
),
|
),
|
||||||
(3, 2, _, 7, _) => Instruction::LD(
|
(3, 2, _, 7, _) => Instruction::LD(
|
||||||
// LD A, (nn)
|
// LD A, (nn)
|
||||||
LDTarget::Register(InstrRegisters::A),
|
LDTarget::Register(InstrRegister::A),
|
||||||
LDTarget::ByteAtAddress(nn),
|
LDTarget::ByteAtAddress(nn),
|
||||||
),
|
),
|
||||||
(3, 3, _, 0, _) => Instruction::JP(
|
(3, 3, _, 0, _) => Instruction::JP(
|
||||||
|
@ -672,29 +737,29 @@ pub enum JPTarget {
|
||||||
ImmediateWord(u16),
|
ImmediateWord(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AllRegisters {
|
pub enum Registers {
|
||||||
Byte(InstrRegisters),
|
Byte(InstrRegister),
|
||||||
Word(RegisterPair),
|
Word(RegisterPair),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MATHTarget {
|
pub enum MATHTarget {
|
||||||
HL,
|
HL,
|
||||||
SP,
|
SP,
|
||||||
Register(InstrRegisters),
|
Register(InstrRegister),
|
||||||
RegisterPair(RegisterPair),
|
RegisterPair(RegisterPair),
|
||||||
ImmediateByte(u8),
|
ImmediateByte(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LDTarget {
|
pub enum LDTarget {
|
||||||
Register(InstrRegisters),
|
Register(InstrRegister),
|
||||||
IndirectRegister(InstrRegisterPairs),
|
IndirectRegister(InstrRegisterPair),
|
||||||
ByteAtAddress(u16),
|
ByteAtAddress(u16),
|
||||||
ImmediateWord(u16),
|
ImmediateWord(u16),
|
||||||
ImmediateByte(u8),
|
ImmediateByte(u8),
|
||||||
RegisterPair(RegisterPair),
|
RegisterPair(RegisterPair),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InstrRegisterPairs {
|
enum InstrRegisterPair {
|
||||||
AF,
|
AF,
|
||||||
BC,
|
BC,
|
||||||
DE,
|
DE,
|
||||||
|
@ -705,7 +770,7 @@ enum InstrRegisterPairs {
|
||||||
DecrementHL,
|
DecrementHL,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InstrRegisters {
|
enum InstrRegister {
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
C,
|
C,
|
||||||
|
@ -728,16 +793,16 @@ pub enum JumpCondition {
|
||||||
struct Table;
|
struct Table;
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn r(index: u8) -> InstrRegisters {
|
pub fn r(index: u8) -> InstrRegister {
|
||||||
match index {
|
match index {
|
||||||
0 => InstrRegisters::B,
|
0 => InstrRegister::B,
|
||||||
1 => InstrRegisters::C,
|
1 => InstrRegister::C,
|
||||||
2 => InstrRegisters::D,
|
2 => InstrRegister::D,
|
||||||
3 => InstrRegisters::E,
|
3 => InstrRegister::E,
|
||||||
4 => InstrRegisters::H,
|
4 => InstrRegister::H,
|
||||||
5 => InstrRegisters::L,
|
5 => InstrRegister::L,
|
||||||
6 => InstrRegisters::IndirectHL,
|
6 => InstrRegister::IndirectHL,
|
||||||
7 => InstrRegisters::A,
|
7 => InstrRegister::A,
|
||||||
_ => unreachable!("Index {} is out of bounds in r[]", index),
|
_ => unreachable!("Index {} is out of bounds in r[]", index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -776,18 +841,18 @@ impl Table {
|
||||||
match fn_index {
|
match fn_index {
|
||||||
0 => Instruction::ADD(
|
0 => Instruction::ADD(
|
||||||
// ADD A, r[z]
|
// ADD A, r[z]
|
||||||
MATHTarget::Register(InstrRegisters::A),
|
MATHTarget::Register(InstrRegister::A),
|
||||||
MATHTarget::Register(Self::r(r_index)),
|
MATHTarget::Register(Self::r(r_index)),
|
||||||
),
|
),
|
||||||
1 => Instruction::ADC(
|
1 => Instruction::ADC(
|
||||||
// ADC A, r[z]
|
// ADC A, r[z]
|
||||||
MATHTarget::Register(InstrRegisters::A),
|
MATHTarget::Register(InstrRegister::A),
|
||||||
MATHTarget::Register(Self::r(r_index)),
|
MATHTarget::Register(Self::r(r_index)),
|
||||||
),
|
),
|
||||||
2 => Instruction::SUB(MATHTarget::Register(Self::r(r_index))), // SUB r[z]
|
2 => Instruction::SUB(MATHTarget::Register(Self::r(r_index))), // SUB r[z]
|
||||||
3 => Instruction::SBC(
|
3 => Instruction::SBC(
|
||||||
// SBC A, r[z]
|
// SBC A, r[z]
|
||||||
MATHTarget::Register(InstrRegisters::A),
|
MATHTarget::Register(InstrRegister::A),
|
||||||
MATHTarget::Register(Self::r(r_index)),
|
MATHTarget::Register(Self::r(r_index)),
|
||||||
),
|
),
|
||||||
4 => Instruction::AND(MATHTarget::Register(Self::r(r_index))), // AND r[z]
|
4 => Instruction::AND(MATHTarget::Register(Self::r(r_index))), // AND r[z]
|
||||||
|
|
Loading…
Reference in New Issue