diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml index 72e7244..fc066c9 100644 --- a/.idea/dictionaries/project.xml +++ b/.idea/dictionaries/project.xml @@ -5,6 +5,12 @@ adcn addhl addsp + dechl + inchl + jpcc + jphl + jrcc + reti rrca rrla diff --git a/src/instructions.rs b/src/instructions.rs index 45ee611..826be15 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,5 +1,5 @@ +use crate::registers::FlagsRegister; use crate::registers::Registers; - struct CPU { registers: Registers, pc: u16, @@ -19,12 +19,46 @@ impl MemoryBus { } } - +#[derive(Clone, Copy)] enum Target { U8Register(TargetRegister), U16Register(TargetU16Register), Address(u16), } +#[derive(Clone, Copy)] +enum Condition { + NZ, // Not Zero + Z, // Zero + NC, // Not Carry + C, // Carry + None +} + +#[derive(Clone, Copy)] +enum LoadTarget{ + CopyR8R8(TargetRegister, TargetRegister), + CopyR8N8(TargetRegister, u8), + CopyR16N16(TargetU16Register, u16), + CopyHLR8(TargetRegister), + CopyHLN8(u8), + CopyR8HL(TargetRegister), + CopyR16A(TargetU16Register), + CopyN16A(u16), + CopyHN16A(u16), + CopyHCA, + CopyAR16(TargetU16Register), + CopyAN16(u16), + CopyHAN16(u16), + CopyHAC, + CopyHLIA, + CopyHLDA, + CopyAHLD, + CopyAHLI, + CopySPN16(u16), + CopyN16SP(u16), + CopyHLSPE8(i8), + CopySPHL, +} enum Instruction { @@ -34,27 +68,60 @@ enum Instruction { ADDSP(u8), AND(Target), BIT(u8, Target), - CALL(u16), - - SUB(TargetRegister), - SBC(TargetRegister), - - OR(TargetRegister), - XOR(TargetRegister), - CP(TargetRegister), - INC(TargetRegister), - DEC(TargetRegister), + CALL(Condition, u16), CCF, - SCF, - RRA, - RLA, - RRCA, + CP(Target), CPL, - + DAA, + DEC(Target), + DECHL(TargetU16Register), + DI, + EI, + HALT, + INC(Target), + INCHL(TargetU16Register), + JP(Condition, u16), + JPHL, + JR(Condition, i8), + LD(LoadTarget), + NOP, + OR(Target), + POP(TargetU16Register), + PUSH(TargetU16Register), + RES(u8, Target), + RET(Condition), + RETI, + RL(Target), + RLC(Target), + RR(Target), + RRC(Target), + RST(u8), + SBC(Target), + SCF, + SET(u8, Target), + SLA(Target), + SRA(Target), + SRL(Target), + STOP, + SUB(Target), + SWAP(Target), + XOR(Target), } +#[derive(Clone, Copy)] enum TargetRegister { A, B, C, D, E, H, L, } +#[derive(Clone, Copy)] enum TargetU16Register {AF, BC, DE, HL, SP, PC} impl CPU { + fn check_condition(&self, condition: Condition) -> bool { + match condition { + Condition::NZ => !self.registers.f.zero, + Condition::Z => self.registers.f.zero, + Condition::NC => !self.registers.f.carry, + Condition::C => self.registers.f.carry, + Condition::None => true, + } + } + fn get_u8_reg_value(&mut self, target: TargetRegister) -> u8 { match target { TargetRegister::A => { self.registers.a } @@ -66,6 +133,17 @@ impl CPU { TargetRegister::L => { self.registers.l } } } + fn set_u8_reg_value(&mut self, target: TargetRegister, value: u8) { + match target { + TargetRegister::A => { self.registers.a = value } + TargetRegister::B => { self.registers.b = value } + TargetRegister::C => { self.registers.c = value } + TargetRegister::D => { self.registers.d = value } + TargetRegister::E => { self.registers.e = value } + TargetRegister::H => { self.registers.h = value } + TargetRegister::L => { self.registers.l = value } + } + } fn get_u16_reg_value(&mut self, target: TargetU16Register) -> u16 { match target { TargetU16Register::AF => {self.registers.get_af()} @@ -76,17 +154,50 @@ impl CPU { TargetU16Register::PC => {self.pc} } } + fn set_u16_reg_value(&mut self, target: TargetU16Register, value: u16) { + match target { + TargetU16Register::AF => {self.registers.set_af(value)} + TargetU16Register::BC => {self.registers.set_bc(value)} + TargetU16Register::DE => {self.registers.set_de(value)} + TargetU16Register::HL => {self.registers.set_hl(value)} + TargetU16Register::SP => {self.sp=value} + TargetU16Register::PC => {self.pc=value} + } + } + fn push_stack(&mut self, value: u16) { + let low = (value & 0xFF) as u8; + let high = (value >> 8) as u8; + self.bus.write_byte(self.sp - 1, high); + self.bus.write_byte(self.sp - 2, low); + self.sp = self.sp.wrapping_sub(2); + } + fn pop_stack(&mut self) -> u16 { + let low = (self.bus.read_byte(self.sp) as u16) << 8; + let high = self.bus.read_byte(self.sp + 1) as u16; + self.sp = self.sp.wrapping_add(2); + high | low + } fn get_target_value(&mut self, target: Target) -> u8 { match target { Target::U8Register(target_register) => { self.get_u8_reg_value(target_register) }, - Target::U16Register(target_register) => { + Target::U16Register(target_register) => { let address = self.get_u16_reg_value(target_register); - self.bus.read_byte(address) + self.bus.read_byte(address) }, Target::Address(address) => { self.bus.read_byte(address) }, } } + fn set_target_value(&mut self, target: Target, value: u8) { + match target { + Target::U8Register(target_register) => { self.set_u8_reg_value(target_register, value) }, + Target::U16Register(target_register) => { + let address = self.get_u16_reg_value(target_register); + self.bus.write_byte(address, value) + }, + Target::Address(address) => { self.bus.write_byte(address, value) }, + } + } /// fn execute(&mut self, instruction: Instruction) { @@ -142,33 +253,311 @@ impl CPU { self.registers.f.subtract = false; self.registers.f.half_carry = true; } - Instruction::CALL(address) => { - // Decrement stack pointer - self.sp = self.sp.wrapping_sub(2); - - let pc = self.pc; - self.bus.write_byte(self.sp + 1, ((pc >> 8) & 0xFF) as u8); - self.bus.write_byte(self.sp, (pc & 0xFF) as u8); - - // Jump to the target address - self.pc = address; + Instruction::CALL(condition, address) => { + if self.check_condition(condition) { + self.sp = self.sp.wrapping_sub(2); + let pc = self.pc; + self.bus.write_byte(self.sp + 1, ((pc >> 8) & 0xFF) as u8); + self.bus.write_byte(self.sp, (pc & 0xFF) as u8); + self.pc = address; + } } - - - - - - Instruction::SUB(target) => { - let value = self.get_u8_reg_value(target); + Instruction::CCF => { + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + self.registers.f.carry = !self.registers.f.carry; + } + Instruction::CP(target) => { + let value = self.get_target_value(target); let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); - self.registers.a = new_value; self.registers.f.zero = new_value == 0; self.registers.f.subtract = true; self.registers.f.carry = did_overflow; self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; } + Instruction::CPL => { + self.registers.a = !self.registers.a; + self.registers.f.subtract = true; + self.registers.f.half_carry = true; + } + Instruction::DAA => { + let new_value; + let did_overflow; + let mut adjustment: u8 = 0; + if self.registers.f.subtract { + if self.registers.f.half_carry { + adjustment += 0x6; + } + if self.registers.f.carry { + adjustment += 0x60; + } + (new_value, did_overflow) = self.registers.a.overflowing_sub(adjustment); + } else { + if self.registers.f.half_carry || self.registers.a & 0xF > 0x9 { + adjustment += 0x6; + } + if self.registers.f.carry || self.registers.a > 0x99 { + adjustment += 0x60; + } + (new_value, did_overflow) = self.registers.a.overflowing_add(adjustment); + } + self.registers.a = new_value; + self.registers.f.carry = did_overflow; + self.registers.f.zero = new_value == 0; + self.registers.f.half_carry = false; + } + Instruction::DEC(target) => { + match target { + Target::U8Register(target) => { + let value = self.get_u8_reg_value(target); + let (new_value, _) = value.overflowing_sub(1); + self.set_u8_reg_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Target::U16Register(target) => { + let value = self.get_u16_reg_value(target); + let new_value = value.wrapping_sub(1); + self.set_u16_reg_value(target, new_value); + } + Target::Address(_) => {} + } + } + Instruction::DECHL(register) => { + let target = Target::U16Register(register); + let value = self.get_target_value(target); + let new_value = value.wrapping_sub(1); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Instruction::DI => {} + Instruction::EI => {} + Instruction::HALT => {todo!();} + + Instruction::INC(target) => { + match target { + Target::U8Register(target) => { + let value = self.get_u8_reg_value(target); + let (new_value, _) = value.overflowing_add(1); + self.set_u8_reg_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Target::U16Register(target) => { + let value = self.get_u16_reg_value(target); + let new_value = value.wrapping_add(1); + self.set_u16_reg_value(target, new_value); + } + Target::Address(_) => {} + } + } + Instruction::INCHL(register) => { + let target = Target::U16Register(register); + let value = self.get_target_value(target); + let new_value = value.wrapping_add(1); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Instruction::JP(condition, address) => { + if self.check_condition(condition) { + self.pc = address; + } + } + Instruction::JPHL => { + self.pc = self.registers.get_hl(); + } + Instruction::JR(condition, offset) => { + if self.check_condition(condition) { + self.pc = if offset.is_negative() { + self.pc.wrapping_sub(offset.abs() as u16) + } else { + self.pc.wrapping_add(offset as u16) + } + } + } + Instruction::LD(target) => { + match target { + LoadTarget::CopyR8R8(dest_register, source_register) => { + let value = self.get_u8_reg_value(source_register); + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR8N8(dest_register, value) => { + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR16N16(dest_register, value) => { + self.set_u16_reg_value(dest_register, value); + } + LoadTarget::CopyHLR8(source_register) => { + let value = self.get_u8_reg_value(source_register); + let address = self.registers.get_hl(); + self.bus.write_byte(address, value); + } + LoadTarget::CopyHLN8(value) => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, value); + } + LoadTarget::CopyR8HL(dest_register) => { + let address = self.registers.get_hl(); + let value = self.bus.read_byte(address); + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR16A(dest_register) => { + let address = self.get_u16_reg_value(dest_register); + self.bus.write_byte(address, self.registers.a); + } + LoadTarget::CopyN16A(address) => { + self.bus.write_byte(address, self.registers.a); + } + LoadTarget::CopyHN16A(address) => { + if address >= 0xFF00 { + self.bus.write_byte(address, self.registers.a) + } + } + LoadTarget::CopyHCA => { + let address = 0xFF00 + self.registers.c as u16; + self.bus.write_byte(address, self.registers.a) + } + LoadTarget::CopyAR16(source_register) => { + let address = self.get_u16_reg_value(source_register); + self.registers.a = self.bus.read_byte(address); + } + LoadTarget::CopyAN16(address) => { + self.registers.a = self.bus.read_byte(address); + } + LoadTarget::CopyHAN16(address) => { + if address >= 0xFF00 { + self.registers.a = self.bus.read_byte(address) + } + } + LoadTarget::CopyHAC => { + self.registers.a = self.bus.read_byte(0xFF00+self.registers.c as u16) + } + LoadTarget::CopyHLIA => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, self.registers.a); + self.registers.set_hl(address.wrapping_add(1)); + } + LoadTarget::CopyHLDA => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, self.registers.a); + self.registers.set_hl(address.wrapping_sub(1)); + } + LoadTarget::CopyAHLI => { + let address = self.registers.get_hl(); + self.registers.a = self.bus.read_byte(address); + self.registers.set_hl(address.wrapping_add(1)); + } + LoadTarget::CopyAHLD => { + let address = self.registers.get_hl(); + self.registers.a = self.bus.read_byte(address); + self.registers.set_hl(address.wrapping_sub(1)); + } + LoadTarget::CopySPN16(value) => { + self.sp = value; + } + LoadTarget::CopyN16SP(address) => { + self.bus.write_byte(address, (0xF & self.sp) as u8); + self.bus.write_byte(address + 1, (self.sp >> 8) as u8); + } + LoadTarget::CopyHLSPE8(value) => { + + let new_value = match value.is_negative() { + true => { self.sp.wrapping_sub(value.abs() as u16) } + false => { self.sp.wrapping_add(value as u16) } + }; + self.registers.set_hl(new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.carry = (new_value & 0xFF) + (self.sp & 0xFF) > 0xFF; + self.registers.f.half_carry = (new_value & 0xF) + (self.sp & 0xF) > 0xF; + + } + LoadTarget::CopySPHL => { + self.sp = self.registers.get_hl(); + } + } + } + Instruction::NOP => {} + Instruction::OR(target) => { + let value = self.get_target_value(target); + self.registers.a = value | self.registers.a; + self.registers.f.zero = self.registers.a == 0; + self.registers.f.subtract = false; + self.registers.f.carry = false; + self.registers.f.half_carry = false; + } + Instruction::POP(target) => { + let value = self.pop_stack(); + self.set_u16_reg_value(target, value); + } + Instruction::PUSH(target) => { + let value = self.get_u16_reg_value(target); + self.push_stack(value); + } + Instruction::RES(bit, target) => { + let mut value = self.get_target_value(target); + value &= !(1 << bit); + self.set_target_value(target, value); + } + Instruction::RET(condition) => { + if self.check_condition(condition) { + self.pc = self.pop_stack(); + } + } + Instruction::RETI => { + self.pc = self.pop_stack(); + } + Instruction::RL(target) => { + let old_value = self.get_target_value(target); + let old_carry = self.registers.f.carry; + self.registers.f.carry = old_value & 0x80 == 0x80; + let new_value = (self.registers.a << 1) | (if old_carry { 0x01 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RLC(target) => { + let old_value = self.get_target_value(target); + self.registers.f.carry = old_value & 0x80 == 0x80; + let new_value = (self.registers.a << 1) | (if self.registers.f.carry { 0x1 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RR(target) => { + let old_value = self.get_target_value(target); + let old_carry = self.registers.f.carry; + self.registers.f.carry = old_value & 0x1 == 0x1; + let new_value = (self.registers.a >> 1) | (if old_carry { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RRC(target) => { + let old_value = self.get_target_value(target); + self.registers.f.carry = old_value & 0x1 == 0x1; + let new_value = (self.registers.a >> 1) | (if self.registers.f.carry { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RST(idx) => { + self.push_stack(self.pc); + let address = self.bus.read_byte((idx as u16) * 8) as u16; + self.pc = address; + } Instruction::SBC(target) => { - let value = self.get_u8_reg_value(target); + let value = self.get_target_value(target); let (mut new_value, did_overflow) = self.registers.a.overflowing_sub(value); new_value -= did_overflow as u8; self.registers.a = new_value; @@ -177,165 +566,72 @@ impl CPU { self.registers.f.carry = did_overflow; self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; } - - Instruction::OR(target) => { - let value = self.get_u8_reg_value(target); - self.registers.a = value | self.registers.a; - self.registers.f.zero = self.registers.a == 0; + Instruction::SCF => { + self.registers.f.carry = true; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::SET(bit, target) => { + let mut value = self.get_target_value(target); + value |= 1 << bit; + self.set_target_value(target, value); + } + Instruction::SLA(target) => { + let value = self.get_target_value(target); + let new_value = value << 1; + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x80 == 0x80; + self.registers.f.half_carry = false; + } + Instruction::SRA(target) => { + let value = self.get_target_value(target); + let new_value = value >> 1 | (if value & 0x80 == 0x80 { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x80 == 0x80; + self.registers.f.half_carry = false; + } + Instruction::SRL(target) => { + let value = self.get_target_value(target); + let new_value = value >> 1; + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x1 == 0x1; + self.registers.f.half_carry = false; + } + Instruction::STOP => { + + } + Instruction::SUB(target) => { + let value = self.get_target_value(target); + let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); + self.registers.a = new_value; + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::SWAP(target) => { + let value = self.get_target_value(target); + let new_value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; self.registers.f.subtract = false; self.registers.f.carry = false; self.registers.f.half_carry = false; - } + } Instruction::XOR(target) => { - let value = self.get_u8_reg_value(target); + let value = self.get_target_value(target); self.registers.a = value ^ self.registers.a; self.registers.f.zero = self.registers.a == 0; self.registers.f.subtract = false; self.registers.f.carry = false; self.registers.f.half_carry = false; } - Instruction::CP(target) => { - let value = self.get_u8_reg_value(target); - let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::INC(target) => { - let (value, new_value) = match target { - TargetRegister::A => { - let value = self.registers.a; - let (new_value, _) = value.overflowing_add(1); - self.registers.a = new_value; - (value, new_value) - }, - TargetRegister::B => { - let value = self.registers.b; - let (new_value, _) = value.overflowing_add(1); - self.registers.b = new_value; - (value, new_value) - }, - TargetRegister::C => { - let value = self.registers.c; - let (new_value, _) = value.overflowing_add(1); - self.registers.c = new_value; - (value, new_value) - }, - TargetRegister::D => { - let value = self.registers.d; - let (new_value, _) = value.overflowing_add(1); - self.registers.d = new_value; - (value, new_value) - }, - TargetRegister::E => { - let value = self.registers.e; - let (new_value, _) = value.overflowing_add(1); - self.registers.e = new_value; - (value, new_value) - }, - TargetRegister::H => { - let value = self.registers.h; - let (new_value, _) = value.overflowing_add(1); - self.registers.h = new_value; - (value, new_value) - }, - TargetRegister::L => { - let value = self.registers.l; - let (new_value, _) = value.overflowing_add(1); - self.registers.l = new_value; - (value, new_value) - } - }; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Instruction::DEC(target) => { - let (value, new_value) = match target { - TargetRegister::A => { - let value = self.registers.a; - let (new_value, _) = value.overflowing_sub(1); - self.registers.a = new_value; - (value, new_value) - }, - TargetRegister::B => { - let value = self.registers.b; - let (new_value, _) = value.overflowing_sub(1); - self.registers.b = new_value; - (value, new_value) - }, - TargetRegister::C => { - let value = self.registers.c; - let (new_value, _) = value.overflowing_sub(1); - self.registers.c = new_value; - (value, new_value) - }, - TargetRegister::D => { - let value = self.registers.d; - let (new_value, _) = value.overflowing_sub(1); - self.registers.d = new_value; - (value, new_value) - }, - TargetRegister::E => { - let value = self.registers.e; - let (new_value, _) = value.overflowing_sub(1); - self.registers.e = new_value; - (value, new_value) - }, - TargetRegister::H => { - let value = self.registers.h; - let (new_value, _) = value.overflowing_sub(1); - self.registers.h = new_value; - (value, new_value) - }, - TargetRegister::L => { - let value = self.registers.l; - let (new_value, _) = value.overflowing_sub(1); - self.registers.l = new_value; - (value, new_value) - } - }; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Instruction::CCF => { - self.registers.f.carry = !self.registers.f.carry; - } - Instruction::SCF => { - self.registers.f.carry = true; - } - Instruction::RRA => { - let old_carry = self.registers.f.carry; - self.registers.f.carry = self.registers.a & 0x1 == 0x1; - self.registers.a = (self.registers.a >> 1) | (if old_carry { 0x80 } else { 0 }); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RLA => { - let old_carry = self.registers.f.carry; - self.registers.f.carry = self.registers.a & 0x80 == 0x80; - self.registers.a = (self.registers.a << 1) | (if old_carry { 0x01 } else { 0 }); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RRCA => { - self.registers.f.carry = self.registers.a & 0x1 == 0x1; - self.registers.a = self.registers.a >> 1; - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::CPL => { - self.registers.a = !self.registers.a; - self.registers.f.subtract = true; - self.registers.f.half_carry = true; - } - - } } }