This repository has been archived on 2024-12-14. You can view files and clone it, but cannot push or open issues or pull requests.
rustboyadvance-ng/src/arm7tdmi/cpu.rs

123 lines
2.5 KiB
Rust
Raw Normal View History

2019-06-25 03:16:14 +01:00
use std::convert::TryFrom;
use crate::num_traits::FromPrimitive;
use super::arm::*;
use super::sysbus::SysBus;
#[derive(Debug, PartialEq)]
pub enum CpuError {
2019-06-25 03:16:14 +01:00
ArmDecodeError(ArmDecodeError),
IllegalInstruction,
}
2019-06-25 03:16:14 +01:00
impl From<ArmDecodeError> for CpuError {
fn from(e: ArmDecodeError) -> CpuError {
CpuError::ArmDecodeError(e)
}
}
pub type CpuResult<T> = Result<T, CpuError>;
#[derive(Debug, PartialEq)]
pub enum CpuState {
ARM,
THUMB,
}
#[derive(Debug, Primitive)]
#[repr(u8)]
enum CpuMode {
User = 0b10000,
Fiq = 0b10001,
Irq = 0b10010,
Supervisor = 0b10011,
Abort = 0b10111,
Undefined = 0b11011,
System = 0b11111,
}
pub struct CpuModeContext {
// r8-r14
banked_gpr: [u32; 7],
spsr: u32,
}
#[derive(Debug)]
pub struct Core {
pc: u32,
// r0-r7
gpr: [u32; 8],
cpsr: u32,
mode: CpuMode,
state: CpuState,
}
impl Core {
pub fn new() -> Core {
Core {
pc: 0,
gpr: [0; 8],
cpsr: 0,
mode: CpuMode::System,
state: CpuState::ARM,
}
}
pub fn get_reg(&self, reg_num: usize) -> u32 {
match reg_num {
0...7 => self.gpr[reg_num],
15 => self.pc,
_ => unimplemented!("TODO banked registers"),
}
}
pub fn set_reg(&mut self, reg_num: usize, val: u32) {
match reg_num {
0...7 => self.gpr[reg_num] = val,
15 => self.pc = val,
_ => unimplemented!("TODO banked registers"),
}
}
/// Resets the cpu
pub fn reset(&mut self) {
self.pc = 0;
self.cpsr = 0;
self.mode = CpuMode::System;
self.state = CpuState::ARM;
}
fn word_size(&self) -> usize {
match self.state {
CpuState::ARM => 4,
CpuState::THUMB => 2,
}
}
fn advance_pc(&mut self) {
self.pc = self.pc.wrapping_add(self.word_size() as u32)
}
fn step_arm(&mut self, sysbus: &mut SysBus) -> CpuResult<()> {
2019-06-25 03:16:14 +01:00
// fetch
let insn = sysbus.read_32(self.pc);
// decode
let insn = ArmInstruction::try_from((insn, self.pc))?;
Ok(())
}
pub fn step(&mut self, sysbus: &mut SysBus) -> CpuResult<()> {
match self.state {
CpuState::ARM => self.step_arm(sysbus)?,
CpuState::THUMB => unimplemented!("thumb not implemented :("),
};
self.advance_pc();
Ok(())
}
}