gb-emu/src/processor.rs

156 lines
5.4 KiB
Rust
Raw Normal View History

2023-01-16 12:13:53 +11:00
use crate::{Inner, Memory, Register, State};
2023-01-16 14:23:43 +11:00
#[allow(dead_code)]
2023-01-16 14:23:06 +11:00
enum FLAGS {
Z = 7,
N = 6,
H = 5,
C = 4,
}
2023-01-16 12:13:53 +11:00
pub struct CPU {
pub memory: Memory,
pub state: State,
}
impl CPU {
pub fn exec_next(&mut self) -> u8 {
let opcode = self.next_opcode();
match opcode {
0x0 => {
// noop
}
2023-01-16 14:23:06 +11:00
0x01 => self.state.bc = self.ld_immediate_word(),
0x02 => unsafe {
let address = self.state.bc.as_u16;
self.memory.set(address, self.state.af.as_u8s.left);
},
0x03 => unsafe { self.state.bc.as_u16 += 1 },
0x04 => unsafe { self.state.bc.as_u8s.left += 1 },
0x05 => unsafe { self.state.bc.as_u8s.left -= 1 },
0x06 => self.state.bc.as_u8s.left = self.ld_immediate_byte(),
0x07 => panic!("RCLA instruction: 0x07"),
0x08 => unsafe {
let address = self.ld_immediate_word().as_u16;
let word = self.state.sp;
self.store_word(address, word);
},
0x09 => unsafe { self.state.hl.as_u16 += self.state.bc.as_u16 },
0x0A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.bc.as_u16) },
0x0B => unsafe { self.state.bc.as_u16 -= 0x1 },
0x0C => unsafe { self.state.bc.as_u8s.right += 0x1 },
0x0D => unsafe { self.state.bc.as_u8s.right -= 0x1 },
0x0E => self.state.bc.as_u8s.right = self.ld_immediate_byte(),
0x0F => panic!("RRCA instruction: 0x0F"),
0x10 => panic!("STOP instruction"),
0x11 => self.state.de = self.ld_immediate_word(),
0x12 => unsafe {
let address = self.state.de.as_u16;
let data = self.state.af.as_u8s.left;
self.memory.set(address, data);
},
0x13 => unsafe { self.state.de.as_u16 -= 0x1 },
0x14 => unsafe { self.state.de.as_u8s.left += 0x1 },
0x15 => unsafe { self.state.de.as_u8s.left -= 0x1 },
0x16 => self.state.de.as_u8s.left = self.ld_immediate_byte(),
0x17 => panic!("RLA instruction: 0x17"),
0x18 => unsafe { self.state.pc.as_u16 += self.ld_immediate_byte() as u16 },
0x19 => unsafe { self.state.hl.as_u16 += self.state.de.as_u16 },
0x1A => unsafe { self.state.af.as_u8s.left = self.memory.get(self.state.de.as_u16) },
0x1B => unsafe { self.state.de.as_u16 -= 1 },
0x1C => unsafe { self.state.de.as_u8s.right += 1 },
0x1D => unsafe { self.state.de.as_u8s.right -= 1 },
0x1E => self.state.de.as_u8s.right = self.ld_immediate_byte(),
0x1F => panic!("RRA instruction: 0x1F"),
0x20 => {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::Z) == 0 {
unsafe { self.state.pc.as_u16 += jump_size as u16 }
}
2023-01-16 12:13:53 +11:00
}
2023-01-16 14:23:06 +11:00
0x21 => self.state.hl = self.ld_immediate_word(),
0x22 => unsafe {
self.memory
.set(self.state.hl.as_u16, self.state.af.as_u8s.left);
self.state.hl.as_u16 += 1;
},
0x23 => unsafe { self.state.hl.as_u16 += 1 },
2023-01-16 12:13:53 +11:00
0x2C => {
unsafe {
self.state.hl.as_u8s.right += 1;
};
}
0x3E => {
self.state.af.as_u8s.left = self.ld_immediate_byte();
}
0x4A => {
unsafe {
self.state.bc.as_u8s.right = self.state.de.as_u8s.left;
};
}
0x4B => {
unsafe {
self.state.bc.as_u8s.right = self.state.de.as_u8s.right;
};
}
0x53 => {
unsafe {
self.state.de.as_u8s.left = self.state.de.as_u8s.right;
};
}
0x66 => {
unsafe {
self.state.hl.as_u8s.left = self.memory.get(self.state.hl.as_u16);
};
}
0xC3 => {
self.state.pc = self.ld_immediate_word();
}
0xEA => {
unsafe {
let address = self.ld_immediate_word().as_u16;
self.memory.set(address, self.state.af.as_u8s.left);
};
}
_ => {
panic!("unimplemented opcode: {:#X}", opcode);
}
};
return opcode;
}
fn next_opcode(&mut self) -> u8 {
unsafe {
let opcode = self.memory.get(self.state.pc.as_u16);
self.state.pc.as_u16 += 0x1;
return opcode;
};
}
2023-01-16 14:23:06 +11:00
fn store_word(&mut self, address: u16, word: Register) {
unsafe {
self.memory.set(address, word.as_u8s.left);
self.memory.set(address + 1, word.as_u8s.right);
};
}
2023-01-16 12:13:53 +11:00
fn ld_immediate_word(&mut self) -> Register {
Register {
as_u8s: Inner {
left: self.next_opcode(),
right: self.next_opcode(),
},
}
}
fn ld_immediate_byte(&mut self) -> u8 {
self.next_opcode()
}
2023-01-16 14:23:06 +11:00
fn get_flag(&mut self, flag: FLAGS) -> u8 {
unsafe {
return self.state.af.as_u8s.right & (1 << flag as u8);
}
}
2023-01-16 12:13:53 +11:00
}