From f7f66d31e024533d82c50df316cd306f6feffb04 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Wed, 18 Jan 2023 22:15:06 +0100 Subject: [PATCH] Add a lot of comments, fix SRLI instruction in print, --- src/simulator/decode.rs | 2 +- src/simulator/machine.rs | 2 +- src/simulator/print.rs | 182 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 182 insertions(+), 4 deletions(-) diff --git a/src/simulator/decode.rs b/src/simulator/decode.rs index 91c8651..b388eb4 100644 --- a/src/simulator/decode.rs +++ b/src/simulator/decode.rs @@ -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, diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 0aab638..d191b74 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -206,7 +206,7 @@ impl Machine { } }, - //TODO store instructions + // store instructions RISCV_ST => { match inst.funct3 { RISCV_ST_STB => { diff --git a/src/simulator/print.rs b/src/simulator/print.rs index 47cb58a..2e37d7a 100644 --- a/src/simulator/print.rs +++ b/src/simulator/print.rs @@ -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 } }