start implementing instructions
This commit is contained in:
@@ -8,6 +8,7 @@ pub enum CpuType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Cpu {
|
pub trait Cpu {
|
||||||
|
fn new() -> Self;
|
||||||
fn get_type() -> CpuType;
|
fn get_type() -> CpuType;
|
||||||
fn get_regs(&mut self) -> &mut Registers;
|
fn get_regs(&mut self) -> &mut Registers;
|
||||||
fn fetch(&self, _: &Memory, _: u64) -> Option<Instruction> {
|
fn fetch(&self, _: &Memory, _: u64) -> Option<Instruction> {
|
||||||
@@ -21,7 +22,7 @@ pub trait Cpu {
|
|||||||
fn advance(&mut self) -> bool {
|
fn advance(&mut self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error>;
|
|
||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
fn should_service_interrupt(&self) -> bool;
|
fn should_service_interrupt(&self) -> bool;
|
||||||
fn update_compare_interrupt(&mut self);
|
fn update_compare_interrupt(&mut self);
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use crate::core::{
|
|||||||
mem::Memory,
|
mem::Memory,
|
||||||
registers::Registers,
|
registers::Registers,
|
||||||
};
|
};
|
||||||
use utils::{
|
use utils::{error::Error, instruction::Instruction};
|
||||||
error::{Error, Severity, Type::UnhandledInstruction},
|
|
||||||
instruction::Instruction,
|
pub mod decode;
|
||||||
};
|
pub mod instructions;
|
||||||
|
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
regs: Registers,
|
regs: Registers,
|
||||||
@@ -15,6 +15,14 @@ pub struct Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Cpu for Interpreter {
|
impl Cpu for Interpreter {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
regs: Registers::new(),
|
||||||
|
delay_slot: false,
|
||||||
|
prev_delay_slot: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_type() -> super::cpu::CpuType {
|
fn get_type() -> super::cpu::CpuType {
|
||||||
Interpreter
|
Interpreter
|
||||||
}
|
}
|
||||||
@@ -65,16 +73,9 @@ impl Cpu for Interpreter {
|
|||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_execute(&mut self, instr: Instruction) -> Result<(), Error> {
|
|
||||||
match instr.opcode() {
|
|
||||||
_ => Err(Error {
|
|
||||||
severity: Severity::Error,
|
|
||||||
err_type: UnhandledInstruction(instr),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
todo!("reset")
|
self.regs = Registers::new();
|
||||||
|
self.delay_slot = false;
|
||||||
|
self.prev_delay_slot = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
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 => {
|
||||||
|
if instr.0 == 0 {
|
||||||
|
Ok(()) // nop
|
||||||
|
} else {
|
||||||
|
Ok(self.sll(instr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Instruction::ADD => Ok(self.add(instr)),
|
||||||
|
Instruction::ADDU => Ok(self.addu(instr)),
|
||||||
|
_ => Err(Error {
|
||||||
|
severity: Severity::Fatal,
|
||||||
|
err_type: UnhandledInstruction(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(instr),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use utils::{
|
||||||
|
error::{Error, Severity, Type::UnhandledInstruction},
|
||||||
|
instruction::Instruction,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::core::interpreter::Interpreter;
|
||||||
|
|
||||||
|
impl Interpreter {
|
||||||
|
pub fn add(&mut self, instr: Instruction) {
|
||||||
|
let rs = self.regs.read::<i64>(instr.rs()) as u32;
|
||||||
|
let rt = self.regs.read::<i64>(instr.rt()) as u32;
|
||||||
|
let (rd, overflow) = rs.overflowing_add(rt);
|
||||||
|
if overflow {
|
||||||
|
todo!("add overflow!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.regs.write(instr.rd(), rd as i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addu(&mut self, instr: Instruction) {
|
||||||
|
let rs = self.regs.read::<i64>(instr.rs()) as i32;
|
||||||
|
let rt = self.regs.read::<i64>(instr.rt()) as i32;
|
||||||
|
let rd = rs + rt;
|
||||||
|
self.regs.write(instr.rd(), rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sll(&mut self, instr: Instruction) {
|
||||||
|
let rd = self.regs.read::<i64>(instr.rt()) << instr.sa();
|
||||||
|
self.regs.write(instr.rd(), rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,16 +5,16 @@ bitfield! {
|
|||||||
pub struct Instruction(pub u32): FromStorage, IntoStorage, DerefStorage {
|
pub struct Instruction(pub u32): FromStorage, IntoStorage, DerefStorage {
|
||||||
pub special: u8 @ 0..6,
|
pub special: u8 @ 0..6,
|
||||||
pub regimm: u8 @ 16..21,
|
pub regimm: u8 @ 16..21,
|
||||||
pub rt: u8 @ 16..21,
|
pub rt: usize @ 16..21,
|
||||||
pub cop_rt: u8 @ 16..21,
|
pub cop_rt: u8 @ 16..21,
|
||||||
pub rs: u8 @ 21..26,
|
pub rs: usize @ 21..26,
|
||||||
pub cop_rs: u8 @ 21..26,
|
pub cop_rs: u8 @ 21..26,
|
||||||
pub opcode: u8 @ 26..32,
|
pub opcode: u8 @ 26..32,
|
||||||
pub imm: u16 @ 0..16,
|
pub imm: u16 @ 0..16,
|
||||||
pub target: u32 @ 0..26,
|
pub target: u32 @ 0..26,
|
||||||
pub funct: u8 @ 0..6,
|
pub funct: u8 @ 0..6,
|
||||||
pub sa: u8 @ 6..11,
|
pub sa: u8 @ 6..11,
|
||||||
pub rd: u8 @ 11..16,
|
pub rd: usize @ 11..16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user