Commit 24a709d0 authored by Arthur Carlsson's avatar Arthur Carlsson

Adding more instructions

parent 5898cb38
Pipeline #5205811 passed with stage
in 1 minute and 53 seconds
......@@ -48,6 +48,10 @@ impl Cpu {
self.instruction(self.pc_reg, instr_fn)
}
pub fn execute_instruction(&mut self, instr: &Instruction) {
self.pc_reg += 4;
}
fn instruction<T: Fn(PhysicalAddr) -> Result<Word, String>>(&self, addr: PhysicalAddr, instr_fn: T) -> Result<Instruction, String> {
decode_instruction(instr_fn(self.virt_to_phys_addr(addr))?)
}
......
......@@ -2,22 +2,37 @@ use types::Word;
#[derive(Debug, PartialEq)]
pub enum Instruction {
IType { opcode: Opcode, rs: u8, rt: u8, imm: u16 }
IType { opcode: Opcode, rs: u8, rt: u8, imm: u16 },
COPz { cpno: u8, copz_opcode: COPzOpcode }
}
#[derive(Debug, PartialEq)]
pub enum Opcode {
LUI
LUI,
DADDI,
ORI,
LW,
ANDI,
BEQL,
ADDIU
}
pub trait ExecuteInstruction {
fn execute_instruction(&mut self, instr: &Instruction);
#[derive(Debug, PartialEq)]
pub enum COPzOpcode {
MT { rt: u8, rd: u8 }
}
pub fn decode_instruction(word: Word) -> Result<Instruction, String> {
match word >> 26 {
0b001111 => Ok(decode_itype_instruction(Opcode::LUI, word)),
_ => Err(format!("Unknown instruction: {}", word))
0b011000 => Ok(decode_itype_instruction(Opcode::DADDI, word)),
0b001101 => Ok(decode_itype_instruction(Opcode::ORI, word)),
0b100011 => Ok(decode_itype_instruction(Opcode::LW, word)),
0b001100 => Ok(decode_itype_instruction(Opcode::ANDI, word)),
0b010100 => Ok(decode_itype_instruction(Opcode::BEQL, word)),
0b001001 => Ok(decode_itype_instruction(Opcode::ADDIU, word)),
0b010000 | 0b010001 | 0b010010 => decode_copz_instruction(word),
_ => Err(format!("Unknown instruction: {:#X}", word))
}
}
......@@ -30,12 +45,33 @@ fn decode_itype_instruction(opcode: Opcode, word: Word) -> Instruction {
}
}
fn decode_copz_instruction(word: Word) -> Result<Instruction, String> {
let cpno = ((word << 28) & 0b11) as u8;
let copz_opcode = match (word >> 21) & 0b11111 {
0b00100 => Some(COPzOpcode::MT { rt: ((word >> 16) & 0b11111) as u8, rd: ((word >> 11) & 0b11111) as u8 }),
_ => None
};
match copz_opcode {
Some(opcode) => Ok(Instruction::COPz { cpno: cpno, copz_opcode: opcode }),
None => Err(format!("Unknown COPz instruction: {:#X}", word))
}
}
#[cfg(test)]
mod tests {
use cpu::reg::GPR;
use super::*;
#[test]
fn test_arne() {
assert_eq!(Ok(Instruction::IType { opcode: Opcode::LUI, rs: 0, rt: 9, imm: 0x3400 }), decode_instruction(0x3c093400));
fn test_decode_itype() {
assert_eq!(Ok(Instruction::IType { opcode: Opcode::LUI, rs: 0, rt: GPR::T1 as u8, imm: 0x3400 }), decode_instruction(0x3c093400));
}
#[test]
fn test_decode_copz() {
assert_eq!(Ok(Instruction::COPz { cpno: 0, copz_opcode: COPzOpcode::MT { rt: GPR::T1 as u8, rd: 12 } }), decode_instruction(0x40896000));
}
}
mod cpu;
mod instruction;
mod reg;
pub use self::cpu::Cpu;
pub enum GPR {
T1 = 9
}
......@@ -33,9 +33,10 @@ impl<'a> N64<'a> {
pub fn step(&mut self) {
match self.cpu.next_instruction(|addr| self.read_word(addr)) {
Err(s) => println!("Error: {}", s),
Err(s) => panic!(s),
Ok(instr) => {
println!("Instruction: {:?}", instr)
println!("Instruction: {:?}", instr);
self.cpu.execute_instruction(&instr)
}
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment