Add a lot of comments, fix SRLI instruction in print,

This commit is contained in:
Quentin Legot 2023-01-18 22:15:06 +01:00
parent 559f94ca21
commit f7f66d31e0
3 changed files with 182 additions and 4 deletions

View File

@ -13,7 +13,7 @@ pub struct Instruction {
pub funct7 : u8,
pub funct7_smaller : u8,
pub funct3 : u8,
pub shamt : u8,
pub shamt : u8, // shamt = imm[5:0] or imm[4:0] (depend of opcode)
pub imm12_I : u16,
pub imm12_S : u16,

View File

@ -206,7 +206,7 @@ impl Machine {
}
},
//TODO store instructions
// store instructions
RISCV_ST => {
match inst.funct3 {
RISCV_ST_STB => {

View File

@ -2,12 +2,34 @@
#![allow(unused_variables)]
use super::decode::{Instruction};
// Instructions type:
// - R: Register / register
// - I: Immediate
// - U: Upper-Immediate
// - S: Store
// - B: Branch (conditional branches...)
// - J: Jump
/// Type: U
///
/// Load upper immediate
///
/// `LUI rd, imm31_12` => `rd <- imm31_12 << 12`
///
pub const RISCV_LUI: u8 = 0x37;
/// Type: U
///
/// Add upper immediate to PC
///
/// `AUIP rd, imm31_12` => `rd <- PC + imm31_12 << 12`
pub const RISCV_AUIPC: u8 = 0x17;
pub const RISCV_JAL: u8 = 0x6f;
pub const RISCV_JALR: u8 = 0x67;
pub const RISCV_BR: u8 = 0x63;
/// Load instruction
///
/// See func3 to know the type of instruction (LD, LW, LH, LB, LWU, LHU, LBU)
pub const RISCV_LD: u8 = 0x3;
pub const RISCV_ST: u8 = 0x23;
pub const RISCV_OPI: u8 = 0x13;
@ -23,41 +45,197 @@ pub const RISCV_BR_BGE: u8 = 0x5;
pub const RISCV_BR_BLTU: u8 = 0x6;
pub const RISCV_BR_BGEU: u8 = 0x7;
/// Type: I
///
/// Load byte (8 bits word)
///
/// `LB rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LB: u8 = 0x0;
/// Type: I
///
/// Load halfword (16 bits word)
///
/// `LH rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LH: u8 = 0x1;
/// Type: I
///
/// Load word (32 bits word)
///
/// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LW: u8 = 0x2;
/// Type: I
///
/// Load doubleword (64-bits word)
///
/// `LD rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LD: u8 = 0x3;
/// Type: I
///
/// Load byte unsigned
///
/// `LBU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LBU: u8 = 0x4;
/// Type: I
///
/// Load halfword unsigned
///
/// `LHU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LHU: u8 = 0x5;
/// Type: I
///
/// Load word unsigned (64 bits word)
///
/// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
pub const RISCV_LD_LWU: u8 = 0x6;
/// Type: S
///
/// Store halfword (SH) (16 bits)
///
/// In case of overflow (rs2 is a 64 bits reg), only the first 16 bits values are stored
///
/// `SH rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
pub const RISCV_ST_STH: u8 = 0x1;
/// Type: S
///
/// Store word (SW) (32 bits)
///
/// In case of overflow (rs2 is a 64 bits reg), only the first 32 bits values are stored
///
/// `SW rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
pub const RISCV_ST_STW: u8 = 0x2;
/// Type: S
///
/// Store byte (SB) (8 bits)
///
/// In case of overflow (rs2 is a 64 bits reg), only the first 8 bits values are stored
///
/// `SB rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
pub const RISCV_ST_STB: u8 = 0x0;
/// Type: S
///
/// Store doubleword (SD) (64 bits)
///
/// `SD rs2, imm12(rs1` => `rs2 -> mem[rs1 + imm12]`
pub const RISCV_ST_STD: u8 = 0x3;
/// Type: I
///
/// Add immediate
///
/// `addi rd, rs1, imm12` => `rd <- rs1 + imm12`
pub const RISCV_OPI_ADDI: u8 = 0x0;
/// Type: I
///
/// Set less than immediate: set rd to 1 if rs1 < imm12, 0 otherwise
///
/// `SLT rd, rs1, imm12` => `rd <- rs1 < imm12 ? 1 : 0`
pub const RISCV_OPI_SLTI: u8 = 0x2;
/// Type: I
///
/// Set less than immediate unsigned : same than SLTI but for unsigned values
pub const RISCV_OPI_SLTIU: u8 = 0x3;
/// Type: I
///
/// XOR immediate instruction
///
/// `XORI rd, rs1, imm12` => `rd <- rs1 ^ imm12`
pub const RISCV_OPI_XORI: u8 = 0x4;
/// Type: I
///
/// OR immediate instruction
///
/// `ORI rd, rs1, imm12` => `rd <- rs1 | imm12`
pub const RISCV_OPI_ORI: u8 = 0x6;
/// Type: I
///
/// AND immediate instruction
///
/// `ANDI rd, rs1, imm12` => `rd <- rs1 & imm12`
pub const RISCV_OPI_ANDI: u8 = 0x7;
/// Type: I
///
/// Shift left logical immediate
///
/// `SLLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
pub const RISCV_OPI_SLLI: u8 = 0x1;
/// Shift right immediate, may be SRAI or SRLI
pub const RISCV_OPI_SRI: u8 = 0x5;
/// type: I
///
/// Shift right arithmetic immediate
///
/// `SRAI rd, rs1, shamt` => `rd <- rs1 >> shamt`
pub const RISCV_OPI_SRI_SRAI: u8 = 0x20;
/// type: I
///
/// Shift right logical immediate
///
/// `SRLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
pub const RISCV_OPI_SRI_SRLI: u8 = 0x0;
/// Type: R
///
/// Add or sub (see RISCV_OP_ADD_ADD or RISCV_OP_ADD_SUB) depending of func7 value
pub const RISCV_OP_ADD: u8 = 0x0;
/// Type: R
///
/// Shift left logical, add a 0 on right of the word
///
/// `SLL rd, rs1, rs2` => `rs <- rs1 << rs2`
pub const RISCV_OP_SLL: u8 = 0x1;
/// Type: R
///
/// Set less than : set rd to 1 if rs1 < rs2, 0 otherwise
///
/// `SLT rd, rs1, rs2` => `rd <- rs1 < rs2 ? 1 : 0`
pub const RISCV_OP_SLT: u8 = 0x2;
/// Type: R
///
/// Set less than unsigned : same than SLT but for unsigned values
pub const RISCV_OP_SLTU: u8 = 0x3;
/// Type: R
///
/// XOR instruction
///
/// `XOR rd, rs1, rs2` => `rd <- rs1 ^ rs2`
pub const RISCV_OP_XOR: u8 = 0x4;
pub const RISCV_OP_SR: u8 = 0x5;
/// Type: R
///
/// OR instruction
///
/// `OR rd, rs1, rs2` => `rd <- rs1 | rs2`
pub const RISCV_OP_OR: u8 = 0x6;
/// Type: R
///
/// AND instruction
///
/// `AND rd, rs1, rs2` => `rd <- rs1 & rs2`
pub const RISCV_OP_AND: u8 = 0x7;
/// Type : R
///
/// Addition
///
/// `ADD rd, rs1, rs2` => `rd <- rs1 + rs2`
pub const RISCV_OP_ADD_ADD: u8 = 0x0;
/// Type: R
///
/// Substract
///
/// `SUB rd, rs1, rs2` => `rd <- rs1 - rs2`
pub const RISCV_OP_ADD_SUB: u8 = 0x20;
/// Type: R
///
/// Shift right logical, add a 0 at the left of the word (should not used for signed values in most cases)
///
/// `SRL rd, rs1, rs2` => `rd <- rs1 >> rs2`
pub const RISCV_OP_SR_SRL: u8 = 0x0;
/// Type: R
///
/// Shift right arithmetic, add a 1 at the left of the word(useful for signed values bacause it keep signed value)
///
/// `SRA rd, rs1, rs2` => `rd <- rs1 >> rs2`
pub const RISCV_OP_SR_SRA: u8 = 0x20;
pub const RISCV_SYSTEM: u8 = 0x73;
@ -217,7 +395,7 @@ pub fn print(ins: Instruction, pc: i32) -> String { //TODO pc should be u64
// SHAMT OR IMM
if ins.funct3 == RISCV_OPI_SRI {
if ins.funct7 == RISCV_OPI_SRI_SRLI {
format!("slrii\t{}, {}, {}", REG_X[rd], REG_X[rs1], ins.shamt)
format!("srli\t{}, {}, {}", REG_X[rd], REG_X[rs1], ins.shamt)
} else {
format!("srai\t{}, {}, {}", REG_X[rd], REG_X[rs1], ins.shamt)
}
@ -295,7 +473,7 @@ pub fn print(ins: Instruction, pc: i32) -> String { //TODO pc should be u64
RISCV_SYSTEM => {
"ecall".to_string()
},
_ => "Unknown".to_string() // Error
_ => todo!("Unknown or currently unsupported opcode") // Change todo! to panic! in the future, I put todo! because there's a lot of opcode currently not implemented
}
}