Skip to content

Commit

Permalink
Add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
YushiOMOTE committed Dec 14, 2019
1 parent 2f54fe5 commit 3a277b6
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 20 deletions.
2 changes: 2 additions & 0 deletions codegen/templates/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,12 @@ fn op_{{i.code | hex}}(arg: u16, cpu: &mut Cpu, mmu: &mut Mmu) -> (usize, usize)
}
{% endfor %}

/// Return the mnemonic string for the given opcode.
pub fn mnem(code: u16) -> &'static str {
MNEMONICS.get(&code).unwrap_or(&"(unknown opcode)")
}

/// Decodes the opecode and actually executes one instruction.
pub fn decode(code: u16, arg: u16, cpu: &mut Cpu, mmu: &mut Mmu) -> (usize, usize) {
trace!("{:04x}: {:04x}: {}", cpu.get_pc(), code, mnem(code));

Expand Down
4 changes: 2 additions & 2 deletions core/examples/pc/hardware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::sync::{
};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use rgy::hardware::{self, Key, Stream, VRAM_HEIGHT, VRAM_WIDTH};
use rgy::{Key, Stream, VRAM_HEIGHT, VRAM_WIDTH};

#[derive(Clone)]
pub struct Hardware {
Expand Down Expand Up @@ -153,7 +153,7 @@ impl Hardware {
}
}

impl hardware::Hardware for Hardware {
impl rgy::Hardware for Hardware {
fn vram_update(&mut self, line: usize, buf: &[u32]) {
let mut vram = self.vram.lock().unwrap();
for i in 0..buf.len() {
Expand Down
57 changes: 55 additions & 2 deletions core/src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use log::*;

use alloc::fmt;

/// Represents CPU state.
#[derive(Clone)]
pub struct Cpu {
a: u8,
Expand Down Expand Up @@ -53,6 +54,7 @@ impl fmt::Display for Cpu {
}

impl Cpu {
/// Create a new CPU state.
pub fn new() -> Cpu {
Cpu {
a: 0,
Expand All @@ -70,11 +72,18 @@ impl Cpu {
}
}

/// Switch the CPU state to halting.
pub fn halt(&mut self) {
debug!("Halted");
// self.halt = true;
// TODO: self.halt = true;
}

/// Execute a single instruction.
///
/// The function fetches an instruction code from the memory,
/// decodes it, and updates the CPU/memory state accordingly.
/// The return value is the number of clock cycles consumed by the instruction.
/// If the CPU is in the halt state, the function does nothing but returns a fixed clock cycle.
pub fn execute(&mut self, mmu: &mut Mmu) -> usize {
if self.halt {
4
Expand All @@ -86,16 +95,20 @@ impl Cpu {
}
}

/// Disable interrupts to this CPU.
pub fn disable_interrupt(&mut self) {
debug!("Disable interrupt");
self.ime = false;
}

/// Enable interrupts to this CPU.
pub fn enable_interrupt(&mut self) {
debug!("Enable interrupt");
self.ime = true;
}

/// Check if pending interrupts in the interrupt controller,
/// and process them if any.
pub fn check_interrupt(&mut self, mmu: &mut Mmu, ic: &Device<Ic>) -> usize {
if !self.ime {
if self.halt {
Expand Down Expand Up @@ -131,24 +144,32 @@ impl Cpu {
self.set_pc(value as u16);
}

pub fn stop(&self) {}
/// Stop the CPU.
pub fn stop(&self) {
// TODO: Stop.
}

/// Gets the value of `z` flag in the flag register.
pub fn get_zf(&self) -> bool {
self.f & 0x80 == 0x80
}

/// Gets the value of `n` flag in the flag register.
pub fn get_nf(&self) -> bool {
self.f & 0x40 == 0x40
}

/// Gets the value of `h` flag in the flag register.
pub fn get_hf(&self) -> bool {
self.f & 0x20 == 0x20
}

/// Gets the value of `c` flag in the flag register.
pub fn get_cf(&self) -> bool {
self.f & 0x10 == 0x10
}

/// Updates the value of `z` flag in the flag register.
pub fn set_zf(&mut self, v: bool) {
if v {
self.f = self.f | 0x80
Expand All @@ -157,6 +178,7 @@ impl Cpu {
}
}

/// Updates the value of `n` flag in the flag register.
pub fn set_nf(&mut self, v: bool) {
if v {
self.f = self.f | 0x40
Expand All @@ -165,6 +187,7 @@ impl Cpu {
}
}

/// Updates the value of `h` flag in the flag register.
pub fn set_hf(&mut self, v: bool) {
if v {
self.f = self.f | 0x20
Expand All @@ -173,6 +196,7 @@ impl Cpu {
}
}

/// Updates the value of `c` flag in the flag register.
pub fn set_cf(&mut self, v: bool) {
if v {
self.f = self.f | 0x10
Expand All @@ -181,126 +205,155 @@ impl Cpu {
}
}

/// Updates the value of `a` register.
pub fn set_a(&mut self, v: u8) {
self.a = v
}

/// Updates the value of `b` register.
pub fn set_b(&mut self, v: u8) {
self.b = v
}

/// Updates the value of `c` register.
pub fn set_c(&mut self, v: u8) {
self.c = v
}

/// Updates the value of `d` register.
pub fn set_d(&mut self, v: u8) {
self.d = v
}

/// Updates the value of `e` register.
pub fn set_e(&mut self, v: u8) {
self.e = v
}

/// Updates the value of `h` register.
pub fn set_h(&mut self, v: u8) {
self.h = v
}

/// Updates the value of `l` register.
pub fn set_l(&mut self, v: u8) {
self.l = v
}

/// Updates the value of `a` and `f` register as a single 16-bit register.
pub fn set_af(&mut self, v: u16) {
self.a = (v >> 8) as u8;
self.f = (v & 0xf0) as u8;
}

/// Updates the value of `b` and `c` register as a single 16-bit register.
pub fn set_bc(&mut self, v: u16) {
self.b = (v >> 8) as u8;
self.c = v as u8;
}

/// Updates the value of `d` and `e` register as a single 16-bit register
pub fn set_de(&mut self, v: u16) {
self.d = (v >> 8) as u8;
self.e = v as u8;
}

/// Updates the value of `h` and `l` register as a single 16-bit register.
pub fn set_hl(&mut self, v: u16) {
self.h = (v >> 8) as u8;
self.l = v as u8;
}

/// Gets the value of `a` register.
pub fn get_a(&self) -> u8 {
self.a
}

/// Gets the value of `b` register.
pub fn get_b(&self) -> u8 {
self.b
}

/// Gets the value of `c` register.
pub fn get_c(&self) -> u8 {
self.c
}

/// Gets the value of `d` register.
pub fn get_d(&self) -> u8 {
self.d
}

/// Gets the value of `e` register.
pub fn get_e(&self) -> u8 {
self.e
}

/// Gets the value of `h` register.
pub fn get_h(&self) -> u8 {
self.h
}

/// Gets the value of `l` register.
pub fn get_l(&self) -> u8 {
self.l
}

/// Gets the value of `a` and `f` register as a single 16-bit register.
pub fn get_af(&self) -> u16 {
(self.a as u16) << 8 | self.f as u16
}

/// Gets the value of `b` and `c` register as a single 16-bit register.
pub fn get_bc(&self) -> u16 {
(self.b as u16) << 8 | self.c as u16
}

/// Gets the value of `d` and `e` register as a single 16-bit register.
pub fn get_de(&self) -> u16 {
(self.d as u16) << 8 | self.e as u16
}

/// Gets the value of `h` and `l` register as a single 16-bit register.
pub fn get_hl(&self) -> u16 {
(self.h as u16) << 8 | self.l as u16
}

/// Gets the value of the program counter.
pub fn get_pc(&self) -> u16 {
self.pc
}

/// Updates the value of the program counter.
pub fn set_pc(&mut self, v: u16) {
self.pc = v
}

/// Gets the value of the stack pointer register.
pub fn get_sp(&self) -> u16 {
self.sp
}

/// Updates the value of the stack pointer register.
pub fn set_sp(&mut self, v: u16) {
self.sp = v
}

/// Pushes a 16-bit value to the stack, updating the stack pointer register.
pub fn push(&mut self, mmu: &mut Mmu, v: u16) {
let p = self.get_sp().wrapping_sub(2);
self.set_sp(self.get_sp().wrapping_sub(2));
mmu.set16(p, v)
}

/// Pops a 16-bit value from the stack, updating the stack pointer register.
pub fn pop(&mut self, mmu: &mut Mmu) -> u16 {
let p = self.get_sp();
self.set_sp(self.get_sp().wrapping_add(2));
mmu.get16(p)
}

/// Fetches an opcode from the memory and returns it with its length.
pub fn fetch(&self, mmu: &Mmu) -> (u16, u16) {
let pc = self.get_pc();

Expand Down
12 changes: 12 additions & 0 deletions core/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,31 @@ use crate::cpu::Cpu;
use crate::device::IoHandler;
use crate::mmu::{MemRead, MemWrite, Mmu};

/// Debugger interface.
///
/// The users of this library can implement this interface to inspect the state of the emulator.
pub trait Debugger: IoHandler {
/// The function is called on the initialization phase.
fn init(&mut self, mmu: &Mmu);

/// The function is called right before the emulator starts executing an instruction. Deprecated.
fn take_cpu_snapshot(&mut self, cpu: Cpu);

/// Decode an instruction.
fn on_decode(&mut self, mmu: &Mmu);

/// Check if the external signal is triggered. Deprecated.
fn check_signal(&mut self);
}

impl dyn Debugger {
/// Create an empty debugger.
pub fn empty() -> NullDebugger {
NullDebugger
}
}

/// Empty debugger which does nothing.
pub struct NullDebugger;

impl Debugger for NullDebugger {
Expand Down
10 changes: 10 additions & 0 deletions core/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ use core::cell::{Ref, RefCell, RefMut};

use crate::mmu::{MemHandler, MemRead, MemWrite, Mmu};

/// The wrapper type for I/O handlers to register to MMU.
pub struct Device<T>(Rc<RefCell<T>>, bool);

impl<T> Device<T> {
/// Create a new device.
pub fn new(inner: T) -> Self {
Self::inner(inner, false)
}

/// Create a new mediater device.
pub fn mediate(inner: T) -> Self {
Self::inner(inner, true)
}
Expand All @@ -18,27 +21,34 @@ impl<T> Device<T> {
Self(Rc::new(RefCell::new(inner)), debug)
}

/// Immutably borrow the underlying I/O handler.
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
self.0.borrow()
}

/// Mutabully borrow the underlying I/O handler.
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
self.0.borrow_mut()
}
}

impl<T: IoHandler> Device<T> {
/// Return the memory-mapped I/O handler of the device.
pub fn handler(&self) -> IoMemHandler<T> {
IoMemHandler(self.0.clone(), self.1)
}
}

/// The trait which allows to hook I/O access from the CPU.
pub trait IoHandler {
/// The function is called when the CPU attempts to read the memory-mapped I/O.
fn on_read(&mut self, mmu: &Mmu, addr: u16) -> MemRead;

/// The function is called when the CPU attempts to write the memory-mapped I/O.
fn on_write(&mut self, mmu: &Mmu, addr: u16, value: u8) -> MemWrite;
}

/// The handler to intercept memory-mapped I/O.
pub struct IoMemHandler<T>(Rc<RefCell<T>>, bool);

impl<T: IoHandler> MemHandler for IoMemHandler<T> {
Expand Down
Loading

0 comments on commit 3a277b6

Please sign in to comment.