traits are so ergonomic and an awesome way to implement imm encoding
This commit is contained in:
@@ -15,6 +15,7 @@ impl DecodeCycle {
|
|||||||
DecodeCycle { extensions: ext }
|
DecodeCycle { extensions: ext }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: speed this up by matching based on the opcode field and then fn3
|
||||||
pub fn decode_exec_inst(
|
pub fn decode_exec_inst(
|
||||||
&self,
|
&self,
|
||||||
inst: rv32::Word,
|
inst: rv32::Word,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use enum_dispatch::*;
|
|||||||
|
|
||||||
use crate::system::rv32;
|
use crate::system::rv32;
|
||||||
use crate::cpu;
|
use crate::cpu;
|
||||||
|
use crate::helpers;
|
||||||
|
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
pub trait Instruction {
|
pub trait Instruction {
|
||||||
@@ -11,6 +12,10 @@ pub trait Instruction {
|
|||||||
fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState);
|
fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ImmediateMode {
|
||||||
|
fn sext_imm(&self) -> rv32::XLen;
|
||||||
|
fn full_imm(&self) -> rv32::XLen;
|
||||||
|
}
|
||||||
|
|
||||||
// Null undecided type
|
// Null undecided type
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
@@ -43,15 +48,75 @@ pub struct IType {
|
|||||||
pub imm: B12,
|
pub imm: B12,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EncodingType {
|
impl ImmediateMode for IType {
|
||||||
R(RType),
|
fn sext_imm(&self) -> rv32::XLen {
|
||||||
I(IType),
|
helpers::sext(self.full_imm(), 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_imm(&self) -> rv32::XLen {
|
||||||
|
self.imm() as rv32::XLen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bitfield]
|
||||||
|
pub struct SType {
|
||||||
|
opcode: B7,
|
||||||
|
imm_4_0: B5,
|
||||||
|
funct3: B3,
|
||||||
|
rs1: B5,
|
||||||
|
rs2: B5,
|
||||||
|
imm_11_5: B7,
|
||||||
|
}
|
||||||
|
|
||||||
|
// imm[11:5] = inst[31:25], imm[4:0] = inst[11:7]
|
||||||
|
impl ImmediateMode for SType {
|
||||||
|
fn sext_imm(&self) -> rv32::XLen {
|
||||||
|
helpers::sext(self.full_imm(), 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_imm(&self) -> rv32::XLen {
|
||||||
|
((self.imm_11_5() as rv32::XLen) << 5) | self.imm_4_0() as rv32::XLen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitfield]
|
||||||
|
pub struct BType {
|
||||||
|
opcode: B7,
|
||||||
|
imm_11: B1,
|
||||||
|
imm_4_1: B4,
|
||||||
|
funct3: B3,
|
||||||
|
rs1: B5,
|
||||||
|
rs2: B5,
|
||||||
|
imm_10_5: B6,
|
||||||
|
imm_12: B1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitfield]
|
||||||
|
pub struct UType {
|
||||||
|
opcode: B7,
|
||||||
|
rd: B5,
|
||||||
|
imm: B20,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bitfield]
|
||||||
|
pub struct JType {
|
||||||
|
opcode: B7,
|
||||||
|
rd: B5,
|
||||||
|
imm_19_12: B8,
|
||||||
|
imm_11: B1,
|
||||||
|
imm_10_1: B10,
|
||||||
|
imm_20: B1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[repr(align(8))]
|
#[repr(align(8))]
|
||||||
pub union GenInstruction {
|
pub union GenInstruction {
|
||||||
pub inst: rv32::Word,
|
pub inst: rv32::Word,
|
||||||
pub null: std::mem::ManuallyDrop<NullType>,
|
pub null: std::mem::ManuallyDrop<NullType>,
|
||||||
pub R: std::mem::ManuallyDrop<RType>,
|
pub R: std::mem::ManuallyDrop<RType>,
|
||||||
pub I: std::mem::ManuallyDrop<IType>,
|
pub I: std::mem::ManuallyDrop<IType>,
|
||||||
|
pub S: std::mem::ManuallyDrop<SType>,
|
||||||
|
pub B: std::mem::ManuallyDrop<BType>,
|
||||||
|
pub U: std::mem::ManuallyDrop<UType>,
|
||||||
|
pub J: std::mem::ManuallyDrop<JType>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ use enum_dispatch::*;
|
|||||||
use strum::EnumIter;
|
use strum::EnumIter;
|
||||||
|
|
||||||
use super::encoding::{GenInstruction, Instruction};
|
use super::encoding::{GenInstruction, Instruction};
|
||||||
use crate::helpers::sext;
|
|
||||||
use crate::cpu;
|
use crate::cpu;
|
||||||
|
use crate::ext::encoding::ImmediateMode;
|
||||||
|
use crate::helpers::sext;
|
||||||
use crate::system::rv32;
|
use crate::system::rv32;
|
||||||
|
|
||||||
#[derive(Default, Copy, Clone)]
|
#[derive(Default, Copy, Clone)]
|
||||||
@@ -25,7 +26,8 @@ impl Instruction for ADDI {
|
|||||||
fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) {
|
fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) {
|
||||||
println!("VM > Executing ADDI");
|
println!("VM > Executing ADDI");
|
||||||
let inst = unsafe { inst.I };
|
let inst = unsafe { inst.I };
|
||||||
state.x[inst.rd() as usize] = state.x[inst.rs1() as usize].wrapping_add(sext(inst.imm() as u32, 32));
|
state.x[inst.rd() as usize] =
|
||||||
|
state.x[inst.rs1() as usize].wrapping_add(inst.sext_imm())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,4 +60,3 @@ pub enum ExtensionI {
|
|||||||
ADDI(ADDI),
|
ADDI(ADDI),
|
||||||
ADD(ADD),
|
ADD(ADD),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user