Skip to content

Commit

Permalink
Add RV64M instructions and handle error in execute_general()
Browse files Browse the repository at this point in the history
  • Loading branch information
Clo91eaf committed Mar 17, 2024
1 parent cd179af commit 3138c0e
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 14 deletions.
15 changes: 12 additions & 3 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ use std::cmp::PartialEq;
use std::num::FpCategory;

use crate::{
bus::{Bus, DRAM_BASE}, devices::{
bus::{Bus, DRAM_BASE},
devices::{
dram::DRAM_SIZE,
uart::UART_IRQ,
virtio_blk::{Virtio, VIRTIO_IRQ},
}, exception::Exception, instructions::{Inst, Instruction}, interrupt::Interrupt
},
exception::Exception,
instructions::Inst,
interrupt::Interrupt,
};

pub mod csr;
Expand Down Expand Up @@ -1000,7 +1004,12 @@ impl Cpu {
/// Execute a general-purpose instruction. Raises an exception if something is wrong,
/// otherwise, returns a fetched instruction. It also increments the program counter by 4 bytes.
fn execute_general(&mut self, inst: u64) -> Result<(), Exception> {
self.inst.set_bits(inst as u32);
match self.inst.set_bits(inst as u32) {
Ok(_) => {}
Err(_) => {
panic!("pc: {:x}, inst: {:x}", self.pc, self.inst.bits);
}
}
// 2. Decode.
let opcode = inst & 0x0000007f;
let rd = self.inst.rd as u64;
Expand Down
33 changes: 22 additions & 11 deletions src/instructions/mod.rs → src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
mod rv64i;
mod rv64m;
use rv64i::rv64i;
use rv64m::rv64m;

#[derive(Copy, Clone, Debug)]
pub enum Instruction {
Register(RegisterType),
Expand All @@ -9,6 +14,7 @@ pub enum Instruction {
ERROR,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub enum RegisterType {
// RV32I
Expand Down Expand Up @@ -38,7 +44,10 @@ pub enum RegisterType {
SRLW,
SRAW,

SRET,
MRET,

SFENCE_VMA,
// RV64M
MULW,
DIVW,
Expand All @@ -47,6 +56,7 @@ pub enum RegisterType {
REMUW,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub enum ImmediateType {
// RV32I
Expand All @@ -71,6 +81,7 @@ pub enum ImmediateType {
ECALL,
EBREAK,
FENCE,
FENCE_I,

CSRRW,
CSRRS,
Expand Down Expand Up @@ -155,22 +166,29 @@ pub struct Inst {

impl Inst {
pub fn new() -> Inst {
// new ipt
let mut ipt :Vec<InstPattern>= vec![];
ipt.extend(rv64i());
ipt.extend(rv64m());

// self
Inst {
bits: 0,
typ: Instruction::ERROR,
type_name: "",
ipt: new_ipt(),
ipt,
rd: 0,
rs1: 0,
rs2: 0,
imm: 0,
}
}

pub fn set_bits<T: Into<u32>>(&mut self, bits: T) {
pub fn set_bits<T: Into<u32>>(&mut self, bits: T) -> anyhow::Result<()> {
self.bits = bits.into();
self.decode().unwrap();
self.decode()?;
(self.rd, self.rs1, self.rs2, self.imm) = self.decode_operand().unwrap();
Ok(())
}

#[rustfmt::skip]
Expand Down Expand Up @@ -226,7 +244,7 @@ impl Inst {
.ipt
.iter()
.find(|p| self.match_inst(p.pattern))
.unwrap();
.ok_or_else(|| {anyhow::anyhow!("Unknown instruction")})?;

self.typ = instruction_pattern.itype;
self.type_name = instruction_pattern.name;
Expand Down Expand Up @@ -272,13 +290,6 @@ pub fn new_ipt() -> Vec<InstPattern> {
InstPattern::new("rem", "0000001 ????? ????? 110 ????? 01100 11", Instruction::Register(RegisterType::REM)),
InstPattern::new("remu", "0000001 ????? ????? 111 ????? 01100 11", Instruction::Register(RegisterType::REMU)),
// rv64I
InstPattern::new("addw", "0000000 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::ADDW)),
InstPattern::new("subw", "0100000 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::SUBW)),
InstPattern::new("sllw", "0000000 ????? ????? 001 ????? 01110 11", Instruction::Register(RegisterType::SLLW)),
InstPattern::new("srlw", "0000000 ????? ????? 101 ????? 01110 11", Instruction::Register(RegisterType::SRLW)),
InstPattern::new("sraw", "0100000 ????? ????? 101 ????? 01110 11", Instruction::Register(RegisterType::SRAW)),

InstPattern::new("mret", "0011000 00010 00000 000 00000 11100 11", Instruction::Register(RegisterType::MRET)),
// rv64M
InstPattern::new("mulw", "0000001 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::MULW)),
InstPattern::new("divw", "0000001 ????? ????? 100 ????? 01110 11", Instruction::Register(RegisterType::DIVW)),
Expand Down
86 changes: 86 additions & 0 deletions src/instructions/rv64i.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use super::*;

#[rustfmt::skip]
pub fn rv32i() -> Vec<InstPattern> {
vec![
InstPattern::new("add", "0000000 ????? ????? 000 ????? 01100 11", Instruction::Register(RegisterType::ADD)),
InstPattern::new("sub", "0100000 ????? ????? 000 ????? 01100 11", Instruction::Register(RegisterType::SUB)),
InstPattern::new("xor", "0000000 ????? ????? 100 ????? 01100 11", Instruction::Register(RegisterType::XOR)),
InstPattern::new("or", "0000000 ????? ????? 110 ????? 01100 11", Instruction::Register(RegisterType::OR)),
InstPattern::new("and", "0000000 ????? ????? 111 ????? 01100 11", Instruction::Register(RegisterType::AND)),
InstPattern::new("sll", "0000000 ????? ????? 001 ????? 01100 11", Instruction::Register(RegisterType::SLL)),
InstPattern::new("srl", "0000000 ????? ????? 101 ????? 01100 11", Instruction::Register(RegisterType::SRL)),
InstPattern::new("sra", "0100000 ????? ????? 101 ????? 01100 11", Instruction::Register(RegisterType::SRA)),
InstPattern::new("slt", "0000000 ????? ????? 010 ????? 01100 11", Instruction::Register(RegisterType::SLT)),
InstPattern::new("sltu", "0000000 ????? ????? 011 ????? 01100 11", Instruction::Register(RegisterType::SLTU)),

InstPattern::new("addi", "??????? ????? ????? 000 ????? 00100 11", Instruction::Immediate(ImmediateType::ADDI)), InstPattern::new("xori", "??????? ????? ????? 100 ????? 00100 11", Instruction::Immediate(ImmediateType::XORI)),
InstPattern::new("ori", "??????? ????? ????? 110 ????? 00100 11", Instruction::Immediate(ImmediateType::ORI)),
InstPattern::new("andi", "??????? ????? ????? 111 ????? 00100 11", Instruction::Immediate(ImmediateType::ANDI)),
InstPattern::new("slli", "000000? ????? ????? 001 ????? 00100 11", Instruction::Immediate(ImmediateType::SLLI)),
InstPattern::new("srli", "000000? ????? ????? 101 ????? 00100 11", Instruction::Immediate(ImmediateType::SRLI)),
InstPattern::new("srai", "010000? ????? ????? 101 ????? 00100 11", Instruction::Immediate(ImmediateType::SRAI)),
InstPattern::new("slti", "??????? ????? ????? 010 ????? 00100 11", Instruction::Immediate(ImmediateType::SLTI)),
InstPattern::new("sltiu", "??????? ????? ????? 011 ????? 00100 11", Instruction::Immediate(ImmediateType::SLTIU)),

InstPattern::new("lb", "??????? ????? ????? 000 ????? 00000 11", Instruction::Immediate(ImmediateType::LB)),
InstPattern::new("lh", "??????? ????? ????? 001 ????? 00000 11", Instruction::Immediate(ImmediateType::LH)),
InstPattern::new("lw", "??????? ????? ????? 010 ????? 00000 11", Instruction::Immediate(ImmediateType::LW)),
InstPattern::new("lbu", "??????? ????? ????? 100 ????? 00000 11", Instruction::Immediate(ImmediateType::LBU)),
InstPattern::new("lhu", "??????? ????? ????? 101 ????? 00000 11", Instruction::Immediate(ImmediateType::LHU)),

InstPattern::new("jalr", "??????? ????? ????? 000 ????? 11001 11", Instruction::Immediate(ImmediateType::JALR)),

InstPattern::new("ebreak", "0000000 00001 00000 000 00000 11100 11", Instruction::Immediate(ImmediateType::EBREAK)),
InstPattern::new("ecall", "0000000 00000 00000 000 00000 11100 11", Instruction::Immediate(ImmediateType::ECALL)),
InstPattern::new("fence", "0000??? ????? 00000 000 00000 00011 11", Instruction::Immediate(ImmediateType::FENCE)),
InstPattern::new("fence_i", "0000000 00000 00000 001 00000 00011 11", Instruction::Immediate(ImmediateType::FENCE_I)),

InstPattern::new("csrrw", "??????? ????? ????? 001 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRW)),
InstPattern::new("csrrs", "??????? ????? ????? 010 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRS)),
InstPattern::new("csrrc", "??????? ????? ????? 011 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRC)),
InstPattern::new("csrrwi", "??????? ????? ????? 101 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRWI)),
InstPattern::new("csrrsi", "??????? ????? ????? 110 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRSI)),
InstPattern::new("csrrci", "??????? ????? ????? 111 ????? 11100 11", Instruction::Immediate(ImmediateType::CSRRCI)),

InstPattern::new("sb", "??????? ????? ????? 000 ????? 01000 11", Instruction::Store(StoreType::SB)),
InstPattern::new("sh", "??????? ????? ????? 001 ????? 01000 11", Instruction::Store(StoreType::SH)),
InstPattern::new("sw", "??????? ????? ????? 010 ????? 01000 11", Instruction::Store(StoreType::SW)),

InstPattern::new("beq", "??????? ????? ????? 000 ????? 11000 11", Instruction::Branch(BranchType::BEQ)),
InstPattern::new("bne", "??????? ????? ????? 001 ????? 11000 11", Instruction::Branch(BranchType::BNE)),
InstPattern::new("blt", "??????? ????? ????? 100 ????? 11000 11", Instruction::Branch(BranchType::BLT)),
InstPattern::new("bge", "??????? ????? ????? 101 ????? 11000 11", Instruction::Branch(BranchType::BGE)),
InstPattern::new("bltu", "??????? ????? ????? 110 ????? 11000 11", Instruction::Branch(BranchType::BLTU)),
InstPattern::new("bgeu", "??????? ????? ????? 111 ????? 11000 11", Instruction::Branch(BranchType::BGEU)),

InstPattern::new("jal", "??????? ????? ????? ??? ????? 11011 11", Instruction::Jump(JumpType::JAL)),
InstPattern::new("lui", "??????? ????? ????? ??? ????? 01101 11", Instruction::Upper(UpperType::LUI)),
InstPattern::new("auipc", "??????? ????? ????? ??? ????? 00101 11", Instruction::Upper(UpperType::AUIPC)),

InstPattern::new("mret", "0011000 00010 00000 000 00000 11100 11", Instruction::Register(RegisterType::MRET)),
InstPattern::new("sret", "0001000 00010 00000 000 00000 11100 11", Instruction::Register(RegisterType::SRET)),
InstPattern::new("sfence.vma", "0001001 ????? ????? 000 00000 11100 11", Instruction::Register(RegisterType::SFENCE_VMA)),
]
}

#[rustfmt::skip]
pub fn rv64i() -> Vec<InstPattern> {
let mut i = vec![
InstPattern::new("lwu", "??????? ????? ????? 110 ????? 00000 11", Instruction::Immediate(ImmediateType::LWU)),
InstPattern::new("ld", "??????? ????? ????? 011 ????? 00000 11", Instruction::Immediate(ImmediateType::LD)),
InstPattern::new("addiw", "??????? ????? ????? 000 ????? 00110 11", Instruction::Immediate(ImmediateType::ADDIW)),
InstPattern::new("slliw", "000000? ????? ????? 001 ????? 00110 11", Instruction::Immediate(ImmediateType::SLLIW)),
InstPattern::new("srliw", "000000? ????? ????? 101 ????? 00110 11", Instruction::Immediate(ImmediateType::SRLIW)),
InstPattern::new("sraiw", "010000? ????? ????? 101 ????? 00110 11", Instruction::Immediate(ImmediateType::SRAIW)),
InstPattern::new("sd", "??????? ????? ????? 011 ????? 01000 11", Instruction::Store(StoreType::SD)),

InstPattern::new("addw", "0000000 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::ADDW)),
InstPattern::new("subw", "0100000 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::SUBW)),
InstPattern::new("sllw", "0000000 ????? ????? 001 ????? 01110 11", Instruction::Register(RegisterType::SLLW)),
InstPattern::new("srlw", "0000000 ????? ????? 101 ????? 01110 11", Instruction::Register(RegisterType::SRLW)),
InstPattern::new("sraw", "0100000 ????? ????? 101 ????? 01110 11", Instruction::Register(RegisterType::SRAW)),
];
i.extend(rv32i());
i
}
30 changes: 30 additions & 0 deletions src/instructions/rv64m.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use super::*;

#[rustfmt::skip]
fn rv32m() -> Vec<InstPattern> {
vec![
// rv32M
InstPattern::new("mul", "0000001 ????? ????? 000 ????? 01100 11", Instruction::Register(RegisterType::MUL)),
InstPattern::new("mulh", "0000001 ????? ????? 001 ????? 01100 11", Instruction::Register(RegisterType::MULH)),
InstPattern::new("mulhsu", "0000001 ????? ????? 010 ????? 01100 11", Instruction::Register(RegisterType::MULHSU)),
InstPattern::new("mulhu", "0000001 ????? ????? 011 ????? 01100 11", Instruction::Register(RegisterType::MULHU)),
InstPattern::new("div", "0000001 ????? ????? 100 ????? 01100 11", Instruction::Register(RegisterType::DIV)),
InstPattern::new("divu", "0000001 ????? ????? 101 ????? 01100 11", Instruction::Register(RegisterType::DIVU)),
InstPattern::new("rem", "0000001 ????? ????? 110 ????? 01100 11", Instruction::Register(RegisterType::REM)),
InstPattern::new("remu", "0000001 ????? ????? 111 ????? 01100 11", Instruction::Register(RegisterType::REMU)),
]
}

#[rustfmt::skip]
pub fn rv64m() -> Vec<InstPattern> {
let mut m = vec![
// rv64M
InstPattern::new("mulw", "0000001 ????? ????? 000 ????? 01110 11", Instruction::Register(RegisterType::MULW)),
InstPattern::new("divw", "0000001 ????? ????? 100 ????? 01110 11", Instruction::Register(RegisterType::DIVW)),
InstPattern::new("divuw", "0000001 ????? ????? 100 ????? 01110 11", Instruction::Register(RegisterType::DIVUW)),
InstPattern::new("remw", "0000001 ????? ????? 110 ????? 01110 11", Instruction::Register(RegisterType::REMW)),
InstPattern::new("remuw", "0000001 ????? ????? 110 ????? 01110 11", Instruction::Register(RegisterType::REMUW)),
];
m.extend(rv32m());
m
}

0 comments on commit 3138c0e

Please sign in to comment.