gb-emu/src/processor/mod.rs

309 lines
8 KiB
Rust
Raw Normal View History

2023-01-17 09:09:53 +11:00
use std::{
mem::transmute,
ops::{BitAnd, BitOr, BitXor},
};
2023-01-16 19:28:03 +11:00
2023-01-16 12:13:53 +11:00
use crate::{Inner, Memory, Register, State};
2023-01-22 09:39:45 +11:00
mod opcodes;
2023-01-16 14:23:43 +11:00
#[allow(dead_code)]
2023-01-22 09:18:07 +11:00
#[derive(PartialEq)]
2023-01-16 14:23:06 +11:00
enum FLAGS {
Z = 7,
N = 6,
H = 5,
C = 4,
}
2023-01-18 13:14:22 +11:00
enum Direction {
Left,
Right,
}
2023-01-16 12:13:53 +11:00
pub struct CPU {
pub memory: Memory,
pub state: State,
2023-01-18 12:45:56 +11:00
pub last_instruction: u8,
pub last_instruction_addr: u16,
2023-01-16 12:13:53 +11:00
}
impl CPU {
2023-01-17 09:09:53 +11:00
pub fn exec_next(&mut self) {
2023-01-18 12:45:56 +11:00
unsafe { self.last_instruction_addr = self.state.pc.as_u16 };
2023-01-16 12:13:53 +11:00
let opcode = self.next_opcode();
2023-01-18 12:45:56 +11:00
self.last_instruction = opcode;
2023-01-22 09:32:19 +11:00
println!(
"exec {:#4X} from pc: {:#X}",
opcode, self.last_instruction_addr
);
2023-01-22 09:39:45 +11:00
self.run_opcode(opcode);
2023-01-16 12:13:53 +11:00
}
fn next_opcode(&mut self) -> u8 {
unsafe {
let opcode = self.memory.get(self.state.pc.as_u16);
self.state.pc.as_u16 = self.state.pc.as_u16.wrapping_add(0x1);
2023-01-16 12:13:53 +11:00
return opcode;
};
}
2023-01-18 14:43:24 +11:00
fn rlc(&mut self, byte: u8) -> u8 {
self.rotate_c(byte, Direction::Left)
}
fn rrc(&mut self, byte: u8) -> u8 {
self.rotate_c(byte, Direction::Right)
}
fn rl(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Left)
}
fn rr(&mut self, byte: u8) -> u8 {
self.rotate(byte, Direction::Right)
}
fn rotate_c(&mut self, byte: u8, direction: Direction) -> u8 {
2023-01-18 13:14:22 +11:00
let (mut rotated, carry) = rotate(byte, &direction);
if carry {
rotated += get_rotation_carry(&direction);
self.set_flag(FLAGS::C);
}
return rotated;
}
2023-01-18 14:43:24 +11:00
fn rotate(&mut self, byte: u8, direction: Direction) -> u8 {
2023-01-18 13:14:22 +11:00
let old_carry = self.get_flag(FLAGS::C);
let (mut rotated, carry) = rotate(byte, &direction);
if old_carry > 0 {
rotated += get_rotation_carry(&direction);
}
if carry {
self.set_flag(FLAGS::C);
}
return rotated;
}
2023-01-18 14:43:24 +11:00
fn sla(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Left)
}
fn sra(&mut self, byte: u8) -> u8 {
let b = get_bit(byte, 7);
let val = self.shift(byte, Direction::Right);
if b {
val + 0b10000000
} else {
val
}
}
fn srl(&mut self, byte: u8) -> u8 {
self.shift(byte, Direction::Right)
}
fn shift(&mut self, byte: u8, direction: Direction) -> u8 {
let (rotated, carry) = rotate(byte, &direction);
if carry {
self.set_flag(FLAGS::C);
}
return rotated;
}
fn bit(&mut self, byte: u8, bit: u8) {
self.set_or_clear_flag(FLAGS::Z, !get_bit(byte, bit));
}
2023-01-16 19:28:03 +11:00
fn rst(&mut self, address: u16) {
self.push(self.state.pc);
self.state.pc.as_u8s.left = 0x0;
self.state.pc.as_u8s.right = self.memory.get(address);
}
fn push(&mut self, register: Register) {
unsafe {
let address = self.state.sp.as_u16;
2023-01-18 14:43:24 +11:00
self.memory
.set(address.wrapping_sub(1), register.as_u8s.right);
self.memory
.set(address.wrapping_sub(2), register.as_u8s.left);
self.state.sp.as_u16 = address.wrapping_sub(2);
2023-01-16 19:28:03 +11:00
}
}
fn pop_word(&mut self) -> Register {
unsafe {
let address = self.state.sp.as_u16;
2023-01-22 09:18:07 +11:00
self.state.sp.as_u16 = self.state.sp.as_u16.wrapping_add(0x2);
2023-01-16 19:28:03 +11:00
Register {
as_u8s: Inner {
left: self.memory.get(address),
2023-01-22 09:18:07 +11:00
right: self.memory.get(address.wrapping_add(1)),
2023-01-16 19:28:03 +11:00
},
}
}
}
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 {
2023-01-18 12:45:56 +11:00
if get_bit(self.state.af.as_u8s.right, flag as u8) {
0x1
} else {
0x0
}
2023-01-16 14:23:06 +11:00
}
}
2023-01-16 19:28:03 +11:00
fn set_flag(&mut self, flag: FLAGS) {
2023-01-22 09:18:07 +11:00
if flag == FLAGS::Z {
println!("setting z flag");
}
2023-01-16 19:28:03 +11:00
unsafe {
2023-01-22 09:18:07 +11:00
println!(
"setting flag: currently {0:#b} / {0:#X}",
self.state.af.as_u8s.right
);
2023-01-16 19:28:03 +11:00
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8);
2023-01-22 09:18:07 +11:00
println!(
" now {0:#b} / {0:#X}",
self.state.af.as_u8s.right
);
2023-01-16 19:28:03 +11:00
};
}
fn clear_flag(&mut self, flag: FLAGS) {
unsafe {
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitand(!(1 << flag as u8));
};
}
fn toggle_flag(&mut self, flag: FLAGS) {
unsafe {
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitxor(1 << flag as u8);
};
}
2023-01-18 12:45:56 +11:00
fn set_or_clear_flag(&mut self, flag: FLAGS, state: bool) {
if state {
self.set_flag(flag)
} else {
self.clear_flag(flag)
}
}
fn add_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
2023-01-22 09:18:07 +11:00
self.set_or_clear_flag(FLAGS::Z, result == 0x0);
self.set_or_clear_flag(
FLAGS::H,
(((first & 0xF).wrapping_add(second & 0xF)) & 0x10) == 0x10,
);
2023-01-18 12:45:56 +11:00
return result;
}
fn add_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_add(second);
self.clear_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
2023-01-22 09:18:07 +11:00
self.set_or_clear_flag(FLAGS::Z, result == 0x0);
self.set_or_clear_flag(
FLAGS::H,
(((first & 0xFFF).wrapping_add(second & 0xFFF)) & 0x1000) == 0x1000,
);
2023-01-18 12:45:56 +11:00
return result;
}
fn sub_u8s(&mut self, first: u8, second: u8) -> u8 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
2023-01-22 09:18:07 +11:00
self.set_or_clear_flag(FLAGS::Z, result == 0x0);
2023-01-18 12:45:56 +11:00
self.set_or_clear_flag(
FLAGS::H,
2023-01-22 09:18:07 +11:00
(((first & 0xF).wrapping_sub(second & 0xF)) & 0x10) == 0x10,
2023-01-18 12:45:56 +11:00
);
return result;
}
fn sub_u16s(&mut self, first: u16, second: u16) -> u16 {
let (result, carry) = first.overflowing_sub(second);
self.set_flag(FLAGS::N);
self.set_or_clear_flag(FLAGS::C, carry);
2023-01-22 09:18:07 +11:00
self.set_or_clear_flag(FLAGS::Z, result == 0x0);
2023-01-18 12:45:56 +11:00
self.set_or_clear_flag(
FLAGS::H,
2023-01-22 09:18:07 +11:00
(((first & 0xFFF).wrapping_sub(second & 0xFFF)) & 0x1000) == 0x1000,
2023-01-18 12:45:56 +11:00
);
return result;
}
2023-01-16 12:13:53 +11:00
}
2023-01-17 09:09:53 +11:00
fn as_signed(unsigned: u8) -> i8 {
unsafe {
return transmute(unsigned);
}
}
2023-01-18 12:45:56 +11:00
fn get_bit(byte: u8, flag: u8) -> bool {
let mask = 1 << flag;
let got = byte & mask;
return got > 0x0;
}
2023-01-18 13:14:22 +11:00
fn rotate(byte: u8, direction: &Direction) -> (u8, bool) {
match direction {
Direction::Left => {
let carry = get_bit(byte, 7);
let r = byte << 1;
return (r, carry);
}
Direction::Right => {
let carry = get_bit(byte, 0);
let r = byte >> 1;
return (r, carry);
}
}
}
fn get_rotation_carry(direction: &Direction) -> u8 {
match direction {
Direction::Left => 0b1,
Direction::Right => 0b10000000,
}
}
2023-01-18 14:43:24 +11:00
fn swap_nibbles(byte: u8) -> u8 {
(byte & 0x0F) << 4 | (byte & 0xF0) >> 4
}
fn res(byte: u8, bit: u8) -> u8 {
byte & !(1 << bit)
}
fn set(byte: u8, bit: u8) -> u8 {
byte | (1 << bit)
}