0xC0 - 0xFF
This commit is contained in:
parent
f07c6a41a3
commit
e4ba687968
|
@ -76,6 +76,7 @@ pub struct Memory {
|
|||
oam: [u8; 160],
|
||||
interrupts: u8,
|
||||
ime: bool,
|
||||
ime_scheduled: u8,
|
||||
io: [u8; 76],
|
||||
}
|
||||
|
||||
|
@ -93,6 +94,7 @@ impl Memory {
|
|||
oam: [0x0; 160],
|
||||
interrupts: 0x0,
|
||||
ime: false,
|
||||
ime_scheduled: 0x0,
|
||||
io: [0xFF; 76],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,10 @@ impl CPU {
|
|||
self.reg.pc.set_low(address);
|
||||
}
|
||||
|
||||
pub(crate) fn ret(&mut self) {
|
||||
self.reg.pc = self.pop_word();
|
||||
}
|
||||
|
||||
pub(crate) fn jr(&mut self, jump: i8) {
|
||||
self.reg.pc = self.reg.pc.wrapping_add_signed(jump.into());
|
||||
}
|
||||
|
|
|
@ -120,6 +120,20 @@ impl CPU {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sp_add(&mut self, first: u16, second: i8) -> u16 {
|
||||
let (result, carry) = first.overflowing_add_signed(second.into());
|
||||
self.clear_flag(Flags::NSubtract);
|
||||
self.clear_flag(Flags::Zero);
|
||||
self.set_or_clear_flag(Flags::Carry, carry);
|
||||
self.set_or_clear_flag(
|
||||
Flags::HalfCarry,
|
||||
(((first & 0xFFF).wrapping_add_signed(<i8 as Into<i16>>::into(second) & 0xFFF))
|
||||
& 0x1000)
|
||||
== 0x1000,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub(crate) fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
|
||||
let (result, carry) = first.overflowing_add(second);
|
||||
self.clear_flag(Flags::NSubtract);
|
||||
|
|
|
@ -6,6 +6,13 @@ use super::{as_signed, res, set, swap_nibbles, Flags, Reg8, SplitRegister, CPU};
|
|||
impl CPU {
|
||||
#[allow(dead_code)]
|
||||
pub fn run_opcode(&mut self, opcode: u8) {
|
||||
if self.memory.ime_scheduled > 0 {
|
||||
self.memory.ime_scheduled = self.memory.ime_scheduled.saturating_sub(1);
|
||||
if self.memory.ime_scheduled == 0 {
|
||||
self.memory.ime = true;
|
||||
}
|
||||
}
|
||||
|
||||
match opcode {
|
||||
0x00 => {
|
||||
// noop
|
||||
|
@ -491,9 +498,201 @@ impl CPU {
|
|||
0xBD => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::L)),
|
||||
0xBE => self.cp(self.reg.get_8(Reg8::A), self.memory.get(self.reg.hl)),
|
||||
0xBF => self.cp(self.reg.get_8(Reg8::A), self.reg.get_8(Reg8::A)),
|
||||
|
||||
_ => {
|
||||
undefined(opcode);
|
||||
0xC0 => {
|
||||
if !self.is_flag(Flags::Zero) {
|
||||
self.ret();
|
||||
}
|
||||
}
|
||||
0xC1 => self.reg.bc = self.pop_word(),
|
||||
0xC2 => {
|
||||
let jump = self.ld_immediate_word();
|
||||
if !self.is_flag(Flags::Zero) {
|
||||
self.reg.pc = jump;
|
||||
}
|
||||
}
|
||||
0xC3 => {
|
||||
let jump = self.ld_immediate_word();
|
||||
self.reg.pc = jump;
|
||||
}
|
||||
0xC4 => {
|
||||
let pc = self.ld_immediate_word();
|
||||
if !self.is_flag(Flags::Zero) {
|
||||
self.push(self.reg.pc);
|
||||
self.reg.pc = pc;
|
||||
}
|
||||
}
|
||||
0xC5 => self.push(self.reg.bc),
|
||||
0xC6 => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.add_u8s(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xC7 => self.rst(0x0),
|
||||
0xC8 => {
|
||||
if self.is_flag(Flags::Zero) {
|
||||
self.ret();
|
||||
}
|
||||
}
|
||||
0xC9 => self.ret(),
|
||||
0xCA => {
|
||||
let jump = self.ld_immediate_word();
|
||||
if self.is_flag(Flags::Zero) {
|
||||
self.reg.pc = jump;
|
||||
}
|
||||
}
|
||||
0xCB => panic!("haven't implemented 0xCB opcodes yet!!"),
|
||||
0xCC => {
|
||||
let pc = self.ld_immediate_word();
|
||||
if self.is_flag(Flags::Zero) {
|
||||
self.push(self.reg.pc);
|
||||
self.reg.pc = pc;
|
||||
}
|
||||
}
|
||||
0xCD => {
|
||||
let pc = self.ld_immediate_word();
|
||||
self.push(self.reg.pc);
|
||||
self.reg.pc = pc;
|
||||
}
|
||||
0xCE => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.adc(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xCF => self.rst(0x08),
|
||||
0xD0 => {
|
||||
if !self.is_flag(Flags::Carry) {
|
||||
self.ret();
|
||||
}
|
||||
}
|
||||
0xD1 => self.reg.de = self.pop_word(),
|
||||
0xD2 => {
|
||||
let jump = self.ld_immediate_word();
|
||||
if !self.is_flag(Flags::Carry) {
|
||||
self.reg.pc = jump;
|
||||
}
|
||||
}
|
||||
0xD4 => {
|
||||
let pc = self.ld_immediate_word();
|
||||
if !self.is_flag(Flags::Carry) {
|
||||
self.push(self.reg.pc);
|
||||
self.reg.pc = pc;
|
||||
}
|
||||
}
|
||||
0xD5 => self.push(self.reg.de),
|
||||
0xD6 => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.sub_u8s(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xD7 => self.rst(0x10),
|
||||
0xD8 => {
|
||||
if self.is_flag(Flags::Carry) {
|
||||
self.ret();
|
||||
}
|
||||
}
|
||||
0xD9 => {
|
||||
self.ret();
|
||||
self.memory.ime = true;
|
||||
}
|
||||
0xDA => {
|
||||
let jump = self.ld_immediate_word();
|
||||
if self.is_flag(Flags::Carry) {
|
||||
self.reg.pc = jump;
|
||||
}
|
||||
}
|
||||
0xDC => {
|
||||
let pc = self.ld_immediate_word();
|
||||
if self.is_flag(Flags::Carry) {
|
||||
self.push(self.reg.pc);
|
||||
self.reg.pc = pc;
|
||||
}
|
||||
}
|
||||
0xDE => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.sbc(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xDF => self.rst(0x18),
|
||||
0xE0 => {
|
||||
let mut addr: u16 = 0x0;
|
||||
addr.set_high(0xFF);
|
||||
addr.set_low(self.ld_immediate_byte());
|
||||
self.memory.set(addr, self.reg.get_8(Reg8::A));
|
||||
}
|
||||
0xE1 => self.reg.hl = self.pop_word(),
|
||||
0xE2 => {
|
||||
let mut addr: u16 = 0x0;
|
||||
addr.set_high(0xFF);
|
||||
addr.set_low(self.reg.get_8(Reg8::C));
|
||||
self.memory.set(addr, self.reg.get_8(Reg8::A));
|
||||
}
|
||||
0xE5 => self.push(self.reg.hl),
|
||||
0xE6 => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.and(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xE7 => self.rst(0x20),
|
||||
0xE8 => {
|
||||
let v = as_signed(self.ld_immediate_byte());
|
||||
self.reg.sp = self.sp_add(self.reg.sp, v);
|
||||
}
|
||||
0xE9 => {
|
||||
self.reg.pc = self.reg.hl;
|
||||
}
|
||||
0xEA => {
|
||||
let addr = self.ld_immediate_word();
|
||||
self.memory.set(addr, self.reg.get_8(Reg8::A));
|
||||
}
|
||||
0xEE => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.xor(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xEF => self.rst(0x28),
|
||||
0xF0 => {
|
||||
let mut addr: u16 = 0x0;
|
||||
addr.set_high(0xFF);
|
||||
addr.set_low(self.ld_immediate_byte());
|
||||
self.reg.set_8(Reg8::A, self.memory.get(addr));
|
||||
}
|
||||
0xF1 => self.reg.af = self.pop_word(),
|
||||
0xF2 => {
|
||||
let mut addr: u16 = 0x0;
|
||||
addr.set_high(0xFF);
|
||||
addr.set_low(self.reg.get_8(Reg8::C));
|
||||
self.reg.set_8(Reg8::A, self.memory.get(addr));
|
||||
}
|
||||
0xF3 => {
|
||||
self.memory.ime = false;
|
||||
self.memory.ime_scheduled = 0;
|
||||
}
|
||||
0xF5 => self.push(self.reg.af),
|
||||
0xF6 => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
let val = self.or(self.reg.get_8(Reg8::A), byte);
|
||||
self.reg.set_8(Reg8::A, val);
|
||||
}
|
||||
0xF7 => self.rst(0x30),
|
||||
0xF8 => {
|
||||
let v = as_signed(self.ld_immediate_byte());
|
||||
self.reg.hl = self.sp_add(self.reg.sp, v);
|
||||
}
|
||||
0xF9 => {
|
||||
self.reg.sp = self.reg.hl;
|
||||
}
|
||||
0xFA => {
|
||||
let addr = self.ld_immediate_word();
|
||||
self.reg.set_8(Reg8::A, self.memory.get(addr));
|
||||
}
|
||||
0xFB => self.memory.ime_scheduled = 2,
|
||||
0xFE => {
|
||||
let byte = self.ld_immediate_byte();
|
||||
self.cp(self.reg.get_8(Reg8::A), byte);
|
||||
}
|
||||
0xFF => self.rst(0x38),
|
||||
0xD3 | 0xDB | 0xDD | 0xE3 | 0xE4 | 0xEB | 0xEC | 0xED | 0xF4 | 0xFC | 0xFD => {
|
||||
undefined(opcode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue