better structure + no need for lifetime specifier in Error. TODO: figure out better name for aforementioned
This commit is contained in:
@@ -18,7 +18,7 @@ pub trait Cpu {
|
|||||||
fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> {
|
fn fetch_then_advance(&mut self, _: &Memory) -> Option<Instruction> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn step(&mut self, mem: &Memory) -> Result<u32, Error<'_>>;
|
fn step(&mut self, mem: &Memory) -> Result<u32, Error>;
|
||||||
fn advance(&mut self) -> bool {
|
fn advance(&mut self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ use crate::core::{
|
|||||||
};
|
};
|
||||||
use utils::{error::Error, instruction::Instruction};
|
use utils::{error::Error, instruction::Instruction};
|
||||||
|
|
||||||
pub mod decode;
|
mod isa;
|
||||||
pub mod instructions;
|
|
||||||
|
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
regs: Registers,
|
regs: Registers,
|
||||||
@@ -65,7 +64,7 @@ impl Cpu for Interpreter {
|
|||||||
Some(instr)
|
Some(instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self, mem: &Memory) -> Result<u32, Error<'_>> {
|
fn step(&mut self, mem: &Memory) -> Result<u32, Error> {
|
||||||
if let Some(instr) = self.fetch_then_advance(mem) {
|
if let Some(instr) = self.fetch_then_advance(mem) {
|
||||||
self.decode_execute(instr)?;
|
self.decode_execute(instr)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
use utils::{
|
|
||||||
error::{Error, Severity, Type::UnhandledInstruction},
|
|
||||||
instruction::Instruction,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::core::interpreter::Interpreter;
|
|
||||||
|
|
||||||
impl Interpreter {
|
|
||||||
pub fn decode_special(&mut self, instr: Instruction) -> Result<(), Error<'_>> {
|
|
||||||
match instr.special() {
|
|
||||||
Instruction::SLL => Ok(self.sll(instr)),
|
|
||||||
Instruction::ADD => Ok(self.add(instr)),
|
|
||||||
Instruction::ADDU => Ok(self.addu(instr)),
|
|
||||||
_ => Err(Error {
|
|
||||||
severity: Severity::Fatal,
|
|
||||||
err_type: UnhandledInstruction("CPU::SpecialFunction", instr),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error<'_>> {
|
|
||||||
match instr.opcode() {
|
|
||||||
Instruction::SPECIAL => self.decode_special(instr),
|
|
||||||
_ => Err(Error {
|
|
||||||
severity: Severity::Error,
|
|
||||||
err_type: UnhandledInstruction("CPU::Opcode", instr),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+36
-18
@@ -1,6 +1,3 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
use utils::{
|
use utils::{
|
||||||
error::{Error, Severity, Type::UnhandledInstruction},
|
error::{Error, Severity, Type::UnhandledInstruction},
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
@@ -9,7 +6,29 @@ use utils::{
|
|||||||
use crate::core::interpreter::Interpreter;
|
use crate::core::interpreter::Interpreter;
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
pub fn add(&mut self, instr: Instruction) {
|
fn decode_special(&mut self, instr: Instruction) -> Result<(), Error> {
|
||||||
|
match instr.special() {
|
||||||
|
Instruction::SLL => Ok(self.sll(instr)),
|
||||||
|
Instruction::ADD => Ok(self.add(instr)),
|
||||||
|
Instruction::ADDU => Ok(self.addu(instr)),
|
||||||
|
_ => Err(Error {
|
||||||
|
severity: Severity::Fatal,
|
||||||
|
err_type: UnhandledInstruction("CPU::SpecialFunction", instr),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error> {
|
||||||
|
match instr.opcode() {
|
||||||
|
Instruction::SPECIAL => self.decode_special(instr),
|
||||||
|
_ => Err(Error {
|
||||||
|
severity: Severity::Error,
|
||||||
|
err_type: UnhandledInstruction("CPU::Opcode", instr),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as u32;
|
let rs = self.regs.read(instr.rs()) as u32;
|
||||||
let rt = self.regs.read(instr.rt()) as u32;
|
let rt = self.regs.read(instr.rt()) as u32;
|
||||||
let (rd, overflow) = rs.overflowing_add(rt);
|
let (rd, overflow) = rs.overflowing_add(rt);
|
||||||
@@ -20,13 +39,13 @@ impl Interpreter {
|
|||||||
self.regs.write(instr.rd(), rd as i32);
|
self.regs.write(instr.rd(), rd as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addu(&mut self, instr: Instruction) {
|
fn addu(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as i32;
|
let rs = self.regs.read(instr.rs()) as i32;
|
||||||
let rt = self.regs.read(instr.rt()) as i32;
|
let rt = self.regs.read(instr.rt()) as i32;
|
||||||
self.regs.write(instr.rd(), rs + rt);
|
self.regs.write(instr.rd(), rs + rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addi(&mut self, instr: Instruction) {
|
fn addi(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as u32;
|
let rs = self.regs.read(instr.rs()) as u32;
|
||||||
let imm = instr.imm() as i16 as i32 as u32;
|
let imm = instr.imm() as i16 as i32 as u32;
|
||||||
let (rt, overflow) = rs.overflowing_add(imm);
|
let (rt, overflow) = rs.overflowing_add(imm);
|
||||||
@@ -36,14 +55,13 @@ impl Interpreter {
|
|||||||
|
|
||||||
self.regs.write(instr.rt(), rt as i32);
|
self.regs.write(instr.rt(), rt as i32);
|
||||||
}
|
}
|
||||||
|
fn addiu(&mut self, instr: Instruction) {
|
||||||
pub fn addiu(&mut self, instr: Instruction) {
|
|
||||||
let rs = self.regs.read(instr.rs()) as i32;
|
let rs = self.regs.read(instr.rs()) as i32;
|
||||||
let imm = instr.imm() as i16 as i32;
|
let imm = instr.imm() as i16 as i32;
|
||||||
self.regs.write(instr.rt(), rs + imm);
|
self.regs.write(instr.rt(), rs + imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dadd(&mut self, instr: Instruction) {
|
fn dadd(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as u64;
|
let rs = self.regs.read(instr.rs()) as u64;
|
||||||
let rt = self.regs.read(instr.rt()) as u64;
|
let rt = self.regs.read(instr.rt()) as u64;
|
||||||
let (rd, overflow) = rs.overflowing_add(rt);
|
let (rd, overflow) = rs.overflowing_add(rt);
|
||||||
@@ -54,13 +72,13 @@ impl Interpreter {
|
|||||||
self.regs.write(instr.rd(), rd as i64);
|
self.regs.write(instr.rd(), rd as i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn daddu(&mut self, instr: Instruction) {
|
fn daddu(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as i64;
|
let rs = self.regs.read(instr.rs()) as i64;
|
||||||
let rt = self.regs.read(instr.rt()) as i64;
|
let rt = self.regs.read(instr.rt()) as i64;
|
||||||
self.regs.write(instr.rd(), rs + rt);
|
self.regs.write(instr.rd(), rs + rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn daddi(&mut self, instr: Instruction) {
|
fn daddi(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs()) as u64;
|
let rs = self.regs.read(instr.rs()) as u64;
|
||||||
let imm = instr.imm() as i16 as i64 as u64;
|
let imm = instr.imm() as i16 as i64 as u64;
|
||||||
let (rt, overflow) = rs.overflowing_add(imm);
|
let (rt, overflow) = rs.overflowing_add(imm);
|
||||||
@@ -71,7 +89,7 @@ impl Interpreter {
|
|||||||
self.regs.write(instr.rt(), rt as i64);
|
self.regs.write(instr.rt(), rt as i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn daddiu(&mut self, instr: Instruction) {
|
fn daddiu(&mut self, instr: Instruction) {
|
||||||
let rs = self.regs.read(instr.rs());
|
let rs = self.regs.read(instr.rs());
|
||||||
let imm = instr.imm() as i16 as i64;
|
let imm = instr.imm() as i16 as i64;
|
||||||
self.regs.write(instr.rt(), rs + imm);
|
self.regs.write(instr.rt(), rs + imm);
|
||||||
@@ -156,14 +174,14 @@ impl Interpreter {
|
|||||||
self.regs.next_pc = addr;
|
self.regs.next_pc = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn b(&mut self, instr: Instruction, cond: bool) {
|
fn b(&mut self, instr: Instruction, cond: bool) {
|
||||||
let imm = instr.imm() as i16;
|
let imm = instr.imm() as i16;
|
||||||
let offset = (imm as i64) << 2;
|
let offset = (imm as i64) << 2;
|
||||||
let address = self.regs.curr_pc + offset;
|
let address = self.regs.curr_pc + offset;
|
||||||
self.branch(cond, address);
|
self.branch(cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blink(&mut self, instr: Instruction, cond: bool) {
|
fn blink(&mut self, instr: Instruction, cond: bool) {
|
||||||
self.regs.write(31, self.regs.next_pc);
|
self.regs.write(31, self.regs.next_pc);
|
||||||
let imm = instr.imm() as i16;
|
let imm = instr.imm() as i16;
|
||||||
let offset = (imm as i64) << 2;
|
let offset = (imm as i64) << 2;
|
||||||
@@ -171,14 +189,14 @@ impl Interpreter {
|
|||||||
self.branch(cond, address);
|
self.branch(cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bl(&mut self, instr: Instruction, cond: bool) {
|
fn bl(&mut self, instr: Instruction, cond: bool) {
|
||||||
let imm = instr.imm() as i16;
|
let imm = instr.imm() as i16;
|
||||||
let offset = (imm as i64) << 2;
|
let offset = (imm as i64) << 2;
|
||||||
let address = self.regs.curr_pc + offset;
|
let address = self.regs.curr_pc + offset;
|
||||||
self.branch_likely(cond, address);
|
self.branch_likely(cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bllink(&mut self, instr: Instruction, cond: bool) {
|
fn bllink(&mut self, instr: Instruction, cond: bool) {
|
||||||
self.regs.write(31, self.regs.next_pc);
|
self.regs.write(31, self.regs.next_pc);
|
||||||
let imm = instr.imm() as i16;
|
let imm = instr.imm() as i16;
|
||||||
let offset = (imm as i64) << 2;
|
let offset = (imm as i64) << 2;
|
||||||
@@ -186,12 +204,12 @@ impl Interpreter {
|
|||||||
self.branch_likely(cond, address);
|
self.branch_likely(cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lui(&mut self, instr: Instruction) {
|
fn lui(&mut self, instr: Instruction) {
|
||||||
let imm = (instr.imm() as i16 as i64) << 16;
|
let imm = (instr.imm() as i16 as i64) << 16;
|
||||||
self.regs.write(instr.rt(), imm);
|
self.regs.write(instr.rt(), imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sll(&mut self, instr: Instruction) {
|
fn sll(&mut self, instr: Instruction) {
|
||||||
if instr.0 == 0 {
|
if instr.0 == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
+6
-6
@@ -63,12 +63,12 @@ impl fmt::Display for AccessType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Type<'a> {
|
pub enum Type {
|
||||||
UnhandledInstruction(&'a str, Instruction),
|
UnhandledInstruction(&'static str, Instruction),
|
||||||
UnhandledMemoryAccess(u32, AccessType),
|
UnhandledMemoryAccess(u32, AccessType),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Display for Type<'a> {
|
impl<'a> fmt::Display for Type {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let err_type = match self {
|
let err_type = match self {
|
||||||
Type::UnhandledInstruction(which_type, instr) => {
|
Type::UnhandledInstruction(which_type, instr) => {
|
||||||
@@ -84,12 +84,12 @@ impl<'a> fmt::Display for Type<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Error<'a> {
|
pub struct Error {
|
||||||
pub severity: Severity,
|
pub severity: Severity,
|
||||||
pub err_type: Type<'a>,
|
pub err_type: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Display for Error<'a> {
|
impl<'a> fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "[{}]: {}", self.severity, self.err_type)
|
write!(f, "[{}]: {}", self.severity, self.err_type)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user